/**
* Copyright (c) 2003-2009, Xith3D Project Group all rights reserved.
*
* Portions based on the Java3D interface, Copyright by Sun Microsystems.
* Many thanks to the developers of Java3D and Sun Microsystems for their
* innovation and design.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the 'Xith3D Project Group' nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) A
* RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE
*/
package org.xith3d.scenegraph;
import java.util.List;
import org.openmali.vecmath2.Matrix3f;
import org.openmali.vecmath2.Matrix4f;
import org.openmali.vecmath2.Point3f;
import org.openmali.vecmath2.Tuple3f;
import org.openmali.vecmath2.Vector3f;
import org.openmali.vecmath2.util.MatrixUtils;
import org.xith3d.utility.geometry.GeometryUtils;
/**
* This class staticly transforms Shapes/GeometryArrays/Points.<br>
* If you want to move, rotate or scale a Shape once or only very rare,
* you should use this class instead of Transform3D, since the transformation
* is not done each frame.
*
* @author Daniel Herring
* @author Marvin Froehlich (aka Qudus)
*/
public final class StaticTransform
{
/*
private static final float PI = FastMath.PI;
private static final float PI_HALF = FastMath.PI_HALF;
private static final float TWO_PI = FastMath.TWO_PI;
*/
/**
* Inplace offsets each of the given vertices by a specified offset.
*
* @param coords vertices array to be modified
* @param offsetX Shift in x dimension
* @param offsetY Shift in y dimension
* @param offsetZ Shift in z dimension
*/
public static void translate( Tuple3f[] coords, float offsetX, float offsetY, float offsetZ )
{
for ( int i = 0; i < coords.length; i++ )
{
coords[ i ].addX( offsetX );
coords[ i ].addY( offsetY );
coords[ i ].addZ( offsetZ );
}
}
/**
* Inplace offsets each of the given vertices by a specified offset.
*
* @param coords vertices array to be modified
* @param offset Shift in x,y,z dimension
*/
public static void translate( Tuple3f[] coords, Tuple3f offset )
{
translate( coords, offset.getX(), offset.getY(), offset.getZ() );
}
/**
* In-place addition of an offset to each point in src.
*
* @param src Object to be changed
* @param offsetX Shift in x dimension
* @param offsetY Shift in y dimension
* @param offsetZ Shift in z dimension
*/
public static void translate( Geometry src, float offsetX, float offsetY, float offsetZ )
{
final int n = src.getVertexCount();
Point3f coord = Point3f.fromPool();
for ( int i = 0; i < n; i++ )
{
src.getCoordinate( i, coord );
coord.addX( offsetX );
coord.addY( offsetY );
coord.addZ( offsetZ );
src.setCoordinate( i, coord );
}
Point3f.toPool( coord );
src.setBoundsDirty();
}
/**
* In-place addition of an offset to each point in src.
*
* @param src Object to be changed
* @param offset Shift in each dimension
*/
public static void translate( Geometry src, Tuple3f offset )
{
translate( src, offset.getX(), offset.getY(), offset.getZ() );
}
/**
* In-place addition of an offset to each point in src.
*
* @param shape Object to be changed
* @param offsetX Shift in x dimension
* @param offsetY Shift in y dimension
* @param offsetZ Shift in z dimension
*
* @return modified shape if successful; null if not
*/
public static <S extends Shape3D> S translate( S shape, float offsetX, float offsetY, float offsetZ )
{
Geometry src = shape.getGeometry();
if ( src == null )
return ( null );
translate( src, offsetX, offsetY, offsetZ );
shape.setGeometry( src );
return ( shape );
}
/**
* In-place addition of an offset to each point in src.
*
* @param shape Object to be changed
* @param offset Shift in each dimension
*
* @return modified shape if successful; null if not
*/
public static <S extends Shape3D> S translate( S shape, Tuple3f offset )
{
return ( translate( shape, offset.getX(), offset.getY(), offset.getZ() ) );
}
/**
* In-place addition of an offset to each point in src.
*
* @param src Object to be changed
* @param offsetX Shift in x dimension
* @param offsetY Shift in y dimension
* @param offsetZ Shift in z dimension
*/
public static void translate( GroupNode src, float offsetX, float offsetY, float offsetZ )
{
List< Shape3D > shapes = src.findAll( Shape3D.class );
for ( int i = 0; i < shapes.size(); i++ )
{
translate( shapes.get( i ), offsetX, offsetY, offsetZ );
}
}
/**
* In-place addition of an offset to each point in src.
*
* @param src Object to be changed
* @param offset Shift in each dimension
*/
public static void translate( GroupNode src, Tuple3f offset )
{
translate( src, offset.getX(), offset.getY(), offset.getZ() );
}
/**
* Prismatically offsets each point.
* i.e.
* x <- x+a11 + a12*y + a13*z
* y <- a21*x + y+a22 + a23*z
* z <- a31*x + a32*y + z+a33
*
* @param coords the Vertices-coordinates to be changed
* @param offset Shift in each dimension
*/
public static void translate( Tuple3f[] coords, Matrix3f offset )
{
for ( int i = 0; i < coords.length; i++ )
{
coords[ i ].set( coords[ i ].getX() + offset.m00() + coords[ i ].getY() * offset.m01() + coords[ i ].getZ() * offset.m02(),
coords[ i ].getX() * offset.m10() + coords[ i ].getY() + offset.m11() + coords[ i ].getZ() * offset.m12(),
coords[ i ].getX() * offset.m20() + coords[ i ].getY() * offset.m21() + coords[ i ].getZ() + offset.m22()
);
}
}
/**
* Prismatically offsets each point in src.
* i.e.
* x <- x+a11 + a12*y + a13*z
* y <- a21*x + y+a22 + a23*z
* z <- a31*x + a32*y + z+a33
*
* @param src Object to be changed
* @param offset Shift in each dimension
*/
public static void translate( Geometry src, Matrix3f offset )
{
final int n = src.getVertexCount();
Point3f coord = Point3f.fromPool();
for ( int i = 0; i < n; i++ )
{
src.getCoordinate( i, coord );
coord.set( coord.getX() + offset.m00() + coord.getY() * offset.m01() + coord.getZ() * offset.m02(),
coord.getX() * offset.m10() + coord.getY() + offset.m11() + coord.getZ() * offset.m12(),
coord.getX() * offset.m20() + coord.getY() * offset.m21() + coord.getZ() + offset.m22()
);
src.setCoordinate( i, coord );
}
Point3f.toPool( coord );
src.setBoundsDirty();
}
/**
* Prismatically offsets each point in the shape.
* i.e.
* x <- x+a11 + a12*y + a13*z
* y <- a21*x + y+a22 + a23*z
* z <- a31*x + a32*y + z+a33
*
* @param shape Object to be changed
* @param offset Shift in each dimension
*
* @return modified shape if successful; null if not
*/
public static <S extends Shape3D> S translate( S shape, Matrix3f offset )
{
Geometry src = shape.getGeometry();
if ( src == null )
return ( null );
translate( src, offset );
shape.setGeometry( src );
return ( shape );
}
/**
* In-place multiplies the vertices by scale.
* i.e. point.x <- scale.x*point.x for all vertices and dimensions
*
* @param coords the Vertices-coordinates to be changed
* @param scaleX Scaling in x dimension
* @param scaleY Scaling in y dimension
* @param scaleZ Scaling in z dimension
*/
public static void scale( Tuple3f[] coords, float scaleX, float scaleY, float scaleZ )
{
for ( int i = 0; i < coords.length; i++ )
{
coords[ i ].mulX( scaleX );
coords[ i ].mulY( scaleY );
coords[ i ].mulZ( scaleZ );
}
}
/**
* In-place multiplies the vertices in src by scale.
* i.e. point.x <- scale.x*point.x for all vertices and dimensions
*
* @param src Object to be changed
* @param scaleX Scaling in x dimension
* @param scaleY Scaling in y dimension
* @param scaleZ Scaling in z dimension
*/
public static void scale( Geometry src, float scaleX, float scaleY, float scaleZ )
{
final int n = src.getVertexCount();
Point3f coord = Point3f.fromPool();
for ( int i = 0; i < n; i++ )
{
src.getCoordinate( i, coord );
coord.mulX( scaleX );
coord.mulY( scaleY );
coord.mulZ( scaleZ );
src.setCoordinate( i, coord );
}
Point3f.toPool( coord );
src.setBoundsDirty();
}
/**
* In-place multiplies the vertices in src by scale.
* i.e. point.x <- scale.x*point.x for all vertices and dimensions
*
* @param src Object to be changed
* @param scale Scaling in each dimension
*/
public static void scale( Geometry src, Tuple3f scale )
{
scale( src, scale.getX(), scale.getY(), scale.getZ() );
}
/**
* In-place multiplies the vertices in src by scale.
* i.e. point.x <- scale.x*point.x for all vertices and dimensions
*
* @param shape Shape to be changed
* @param scaleX Scaling in x dimension
* @param scaleY Scaling in y dimension
* @param scaleZ Scaling in z dimension
*
* @return modified shape if successful; null if not
*/
public static <S extends Shape3D> S scale( S shape, float scaleX, float scaleY, float scaleZ )
{
Geometry src = shape.getGeometry();
if ( src == null )
return ( null );
scale( src, scaleX, scaleY, scaleZ );
shape.setGeometry( src );
return ( shape );
}
/**
* In-place multiplies the vertices in src by scale.
* i.e. point.x <- scale*point.x for all vertices and dimensions
*
* @param src Object to be changed
* @param scale Scaling factor
*/
public static void scale( Geometry src, float scale )
{
scale( src, scale, scale, scale );
}
/**
* In-place multiplies the vertices in src by scale.
* i.e. point.x <- scale.x*point.x for all vertices and dimensions
*
* @param shape Shape to be changed
* @param scale Scaling in each dimension
*
* @return modified shape if successful; null if not
*/
public static <S extends Shape3D> S scale( S shape, Tuple3f scale )
{
return ( scale( shape, scale.getX(), scale.getY(), scale.getZ() ) );
}
/**
* In-place multiplies the vertices in src by scale.
* i.e. point.x <- scale*point.x for all vertices and dimensions
*
* @param shape Object to be changed
* @param scale Scaling factor
*
* @return modified shape if successful; null if not
*/
public static <S extends Shape3D> S scale( S shape, float scale )
{
Geometry src = shape.getGeometry();
if ( src == null )
return ( null );
scale( src, scale );
shape.setGeometry( src );
return ( shape );
}
/**
* In-place multiplies each point by A.
* i.e. point <- A*point for all vertices
* This allows for arbitrary scaling, rotation, and reflection.
*
* @param coords the Vertices-coordinates to be changed
* @param m Scaling matrix
*/
public static void transform( Tuple3f[] coords, Matrix3f m )
{
for ( int i = 0; i < coords.length; i++ )
{
coords[ i ].set( m.m00() * coords[ i ].getX() + m.m01() * coords[ i ].getY() + m.m02() * coords[ i ].getZ(),
m.m10() * coords[ i ].getX() + m.m11() * coords[ i ].getY() + m.m12() * coords[ i ].getZ(),
m.m20() * coords[ i ].getX() + m.m21() * coords[ i ].getY() + m.m22() * coords[ i ].getZ()
);
}
}
/**
* In-place multiplies each point in src by A.
* i.e. point <- A*point for all vertices
* This allows for arbitrary scaling, rotation, and reflection.
*
* @param src Shape to be changed
* @param m Scaling matrix
*/
public static void transform( Geometry src, Matrix3f m )
{
final int n = src.getVertexCount();
Point3f coord = Point3f.fromPool();
for ( int i = 0; i < n; i++ )
{
src.getCoordinate( i, coord );
coord.set( m.m00() * coord.getX() + m.m01() * coord.getY() + m.m02() * coord.getZ(),
m.m10() * coord.getX() + m.m11() * coord.getY() + m.m12() * coord.getZ(),
m.m20() * coord.getX() + m.m21() * coord.getY() + m.m22() * coord.getZ()
);
src.setCoordinate( i, coord );
}
Point3f.toPool( coord );
src.setBoundsDirty();
}
/**
* In-place multiplies each point in src by A.
* i.e. point <- A*point for all vertices
* This allows for arbitrary scaling, rotation, and reflection.
*
* @param shape Shape to be changed
* @param m Scaling matrix
* @return modified shape if successful; null if not
*/
public static <S extends Shape3D> S transform( S shape, Matrix3f m )
{
Geometry src = shape.getGeometry();
if ( src == null )
return ( null );
transform( src, m );
shape.setGeometry( src );
return ( shape );
}
/**
* In-place multiplies each point by A.
* i.e. point <- A*point for all vertices
* This allows for arbitrary scaling, rotation, and reflection.
*
* @param coords the Vertices-coordinates to be changed
* @param m transformation matrix
*/
public static void transform( Point3f[] coords, Matrix4f m )
{
for ( int i = 0; i < coords.length; i++ )
{
m.transform( coords[ i ] );
}
}
/**
* In-place multiplies each point in src by A.
* i.e. point <- A*point for all vertices
* This allows for arbitrary scaling, rotation, and reflection.
*
* @param src Shape to be changed
* @param m transformation matrix
*/
public static void transform( Geometry src, Matrix4f m )
{
final int n = src.getVertexCount();
Point3f coord = Point3f.fromPool();
for ( int i = 0; i < n; i++ )
{
src.getCoordinate( i, coord );
m.transform( coord );
src.setCoordinate( i, coord );
}
Point3f.toPool( coord );
src.setBoundsDirty();
}
/**
* In-place multiplies each point in src by A.
* i.e. point <- A*point for all vertices
* This allows for arbitrary scaling, rotation, and reflection.
*
* @param shape Shape to be changed
* @param m transformation matrix
* @return modified shape if successful; null if not
*/
public static <S extends Shape3D> S transform( S shape, Matrix4f m )
{
Geometry src = shape.getGeometry();
if ( src == null )
return ( null );
transform( src, m );
shape.setGeometry( src );
return ( shape );
}
/**
* Rotates the geometry by angle theta about the given axis.
*
* @param coords the vertices-coordinates to change
* @param axisX Rotation axis x-component
* @param axisY Rotation axis x-component
* @param axisZ Rotation axis x-component
* @param theta Rotation angle
*/
public static void rotate( Tuple3f[] coords, float axisX, float axisY, float axisZ, float theta )
{
transform( coords, MatrixUtils.getRotationMatrix( axisX, axisY, axisZ, theta ) );
}
/**
* Rotates the geometry by angle theta about the x-axis.
*
* @param coords the vertices-coordinates to change
* @param theta Rotation angle
*/
public static void rotateX( Tuple3f[] coords, float theta )
{
rotate( coords, 1.0f, 0.0f, 0.0f, theta );
}
/**
* Rotates the geometry by angle theta about the y-axis.
*
* @param coords the vertices-coordinates to change
* @param theta Rotation angle
*/
public static void rotateY( Tuple3f[] coords, float theta )
{
rotate( coords, 0.0f, 1.0f, 0.0f, theta );
}
/**
* Rotates the geometry by angle theta about the z-axis.
*
* @param coords the vertices-coordinates to change
* @param theta Rotation angle
*/
public static void rotateZ( Tuple3f[] coords, float theta )
{
rotate( coords, 0.0f, 0.0f, 1.0f, theta );
}
/**
* Rotates the geometry by angle theta about the given axis.
*
* @param src Shape to be changed
* @param axisX Rotation axis x-component
* @param axisY Rotation axis x-component
* @param axisZ Rotation axis x-component
* @param theta Rotation angle
*/
public static void rotate( Geometry src, float axisX, float axisY, float axisZ, float theta )
{
Matrix3f m = MatrixUtils.getRotationMatrix( axisX, axisY, axisZ, theta );
transform( src, m );
// If there are normals, then they also need to be rotated!
if ( src.hasNormals() )
{
final int n = src.getVertexCount();
Vector3f normal = Vector3f.fromPool();
for ( int i = 0; i < n; i++ )
{
src.getNormal( i, normal );
normal.set( m.m00() * normal.getX() + m.m01() * normal.getY() + m.m02() * normal.getZ(),
m.m10() * normal.getX() + m.m11() * normal.getY() + m.m12() * normal.getZ(),
m.m20() * normal.getX() + m.m21() * normal.getY() + m.m22() * normal.getZ()
);
src.setNormal( i, normal );
}
final Vector3f[] normals = GeometryUtils.getNormals( src );
transform( normals, m );
src.setNormals( 0, normals );
}
}
/**
* Rotates the geometry by angle theta about the x-axis.
*
* @param src Shape to be changed
* @param theta Rotation angle
*/
public static void rotateX( Geometry src, float theta )
{
rotate( src, 1.0f, 0.0f, 0.0f, theta );
}
/**
* Rotates the geometry by angle theta about the y-axis.
*
* @param src Shape to be changed
* @param theta Rotation angle
*/
public static void rotateY( Geometry src, float theta )
{
rotate( src, 0.0f, 1.0f, 0.0f, theta );
}
/**
* Rotates the geometry by angle theta about the z-axis.
*
* @param src Shape to be changed
* @param theta Rotation angle
*/
public static void rotateZ( Geometry src, float theta )
{
rotate( src, 0.0f, 0.0f, 1.0f, theta );
}
/**
* Rotates the geometry by angle theta about the given axis.
*
* @param src Shape to be changed
* @param axis Rotation axis
* @param theta Rotation angle
*/
public static void rotate( Geometry src, Tuple3f axis, float theta )
{
rotate( src, axis.getX(), axis.getY(), axis.getZ(), theta );
}
/**
* Rotates the geometry by angle theta about the given axis.
*
* @param shape Shape to be changed
* @param axisX Rotation axis x-component
* @param axisY Rotation axis x-component
* @param axisZ Rotation axis x-component
* @param theta Rotation angle
* @return modified shape if successful; null if not
*/
public static <S extends Shape3D> S rotate( S shape, float axisX, float axisY, float axisZ, float theta )
{
Geometry src = shape.getGeometry();
if ( src == null )
return ( null );
rotate( src, axisX, axisY, axisZ, theta );
shape.setGeometry( src );
return ( shape );
}
/**
* Rotates the geometry by angle theta about the x-axis.
*
* @param shape Shape to be changed
* @param theta Rotation angle
* @return modified shape if successful; null if not
*/
public static <S extends Shape3D> S rotateX( S shape, float theta )
{
return ( rotate( shape, 1.0f, 0.0f, 0.0f, theta ) );
}
/**
* Rotates the geometry by angle theta about the y-axis.
*
* @param shape Shape to be changed
* @param theta Rotation angle
* @return modified shape if successful; null if not
*/
public static <S extends Shape3D> S rotateY( S shape, float theta )
{
return ( rotate( shape, 0.0f, 1.0f, 0.0f, theta ) );
}
/**
* Rotates the geometry by angle theta about the z-axis.
*
* @param shape Shape to be changed
* @param theta Rotation angle
* @return modified shape if successful; null if not
*/
public static <S extends Shape3D> S rotateZ( S shape, float theta )
{
return ( rotate( shape, 0.0f, 0.0f, 1.0f, theta ) );
}
/**
* Rotates the geometry by angle theta about the given axis.
*
* @param shape Shape to be changed
* @param axis Rotation axis
* @param theta Rotation angle
* @return modified shape if successful; null if not
*/
public static <S extends Shape3D> S rotate( S shape, Tuple3f axis, float theta )
{
return ( rotate( shape, axis.getX(), axis.getY(), axis.getZ(), theta ) );
}
/**
* In-place mirrors the vertices by the xy-plane.
* Therefore the z-coordinate is inverted.
*
* @param coords the vertices-coordinates to change
*/
public static void mirrorXY( Tuple3f[] coords )
{
for ( int i = 0; i < coords.length; i++ )
{
coords[ i ].mulZ( -1f );
}
}
/**
* In-place mirrors the vertices by the xy-plane.
* Therefore the z-coordinate is inverted.
*
* @param coords the vertices-coordinates to change
*/
public static void mirrorYZ( Tuple3f[] coords )
{
for ( int i = 0; i < coords.length; i++ )
{
coords[ i ].mulX( -1f );
}
}
/**
* In-place mirrors the vertices by the xy-plane.
* Therefore the z-coordinate is inverted.
*
* @param coords the vertices-coordinates to change
*/
public static void mirrorZX( Tuple3f[] coords )
{
for ( int i = 0; i < coords.length; i++ )
{
coords[ i ].mulY( -1f );
}
}
/**
* In-place mirrors the vertices by the xy-plane.
* Therefore the z-coordinate is inverted.
*
* @param src Object to be changed
*/
public static void mirrorXY( Geometry src )
{
final int n = src.getVertexCount();
Point3f coord = Point3f.fromPool();
for ( int i = 0; i < n; i++ )
{
src.getCoordinate( i, coord );
coord.mulZ( -1f );
src.setCoordinate( i, coord );
}
Point3f.toPool( coord );
src.setBoundsDirty();
// If there are normals, then they also need to be rotated!
if ( src.hasNormals() )
{
Vector3f normal = Vector3f.fromPool();
for ( int i = 0; i < n; i++ )
{
src.getNormal( i, normal );
normal.mulZ( -1f );
src.setNormal( i, normal );
}
Vector3f.toPool( normal );
}
}
/**
* In-place mirrors the vertices by the xy-plane.
* Therefore the z-coordinate is inverted.
*
* @param src Object to be changed
*/
public static void mirrorYZ( Geometry src )
{
final int n = src.getVertexCount();
Point3f coord = Point3f.fromPool();
for ( int i = 0; i < n; i++ )
{
src.getCoordinate( i, coord );
coord.mulX( -1f );
src.setCoordinate( i, coord );
}
Point3f.toPool( coord );
src.setBoundsDirty();
// If there are normals, then they also need to be rotated!
if ( src.hasNormals() )
{
Vector3f normal = Vector3f.fromPool();
for ( int i = 0; i < n; i++ )
{
src.getNormal( i, normal );
normal.mulX( -1f );
src.setNormal( i, normal );
}
Vector3f.toPool( normal );
}
}
/**
* In-place mirrors the vertices by the xy-plane.
* Therefore the z-coordinate is inverted.
*
* @param src Object to be changed
*/
public static void mirrorZX( Geometry src )
{
final int n = src.getVertexCount();
Point3f coord = Point3f.fromPool();
for ( int i = 0; i < n; i++ )
{
src.getCoordinate( i, coord );
coord.mulY( -1f );
src.setCoordinate( i, coord );
}
Point3f.toPool( coord );
src.setBoundsDirty();
// If there are normals, then they also need to be rotated!
if ( src.hasNormals() )
{
Vector3f normal = Vector3f.fromPool();
for ( int i = 0; i < n; i++ )
{
src.getNormal( i, normal );
normal.mulY( -1f );
src.setNormal( i, normal );
}
Vector3f.toPool( normal );
}
}
/**
* In-place mirrors the vertices by the xy-plane.
* Therefore the z-coordinate is inverted.
*
* @param shape Shape to be changed
*
* @return modified shape if successful; null if not
*/
public static <S extends Shape3D> S mirrorXY( S shape )
{
Geometry src = shape.getGeometry();
if ( src == null )
return ( null );
mirrorXY( src );
shape.setGeometry( src );
return ( shape );
}
/**
* In-place mirrors the vertices by the xy-plane.
* Therefore the z-coordinate is inverted.
*
* @param shape Shape to be changed
*
* @return modified shape if successful; null if not
*/
public static <S extends Shape3D> S mirrorYZ( S shape )
{
Geometry src = shape.getGeometry();
if ( src == null )
return ( null );
mirrorYZ( src );
shape.setGeometry( src );
return ( shape );
}
/**
* In-place mirrors the vertices by the xy-plane.
* Therefore the z-coordinate is inverted.
*
* @param shape Shape to be changed
*
* @return modified shape if successful; null if not
*/
public static <S extends Shape3D> S mirrorZX( S shape )
{
Geometry src = shape.getGeometry();
if ( src == null )
return ( null );
mirrorZX( src );
shape.setGeometry( src );
return ( shape );
}
/**
* Applies a general quadratic transform.
* p <- p + A + B*p + p*C*p
*
* i.e.
* x <- x + a0 + (b00*x + b01*y + b02*z) + x*(c00*x + c01*y + c02*z)
* y <- y + a1 + (b10*x + b11*y + b12*z) + y*(c10*x + c11*y + c12*z)
* z <- z + a2 + (b20*x + b21*y + b22*z) + z*(c20*x + c21*y + c22*z)
*
* @param src Shape to be changed
* @param A Constant offset
* @param B Linear terms
* @param C Quadratic terms
*/
public static void quadratic( Geometry src, Tuple3f A, Matrix3f B, Matrix3f C )
{
final int n = src.getVertexCount();
Point3f coord = Point3f.fromPool();
float x, y, z;
for ( int i = 0; i < n; i++ )
{
src.getCoordinate( i, coord );
x = coord.getX();
y = coord.getY();
z = coord.getZ();
coord.set( x + A.getX() + ( B.m00() * x + B.m01() * y + B.m02() * z ) + x * ( C.m00() * x + C.m01() * y + C.m02() * z ),
y + A.getY() + ( B.m10() * x + B.m11() * y + B.m12() * z ) + x * ( C.m10() * x + C.m11() * y + C.m12() * z ),
z + A.getZ() + ( B.m20() * x + B.m21() * y + B.m22() * z ) + x * ( C.m20() * x + C.m21() * y + C.m22() * z )
);
src.setCoordinate( i, coord );
}
Point3f.toPool( coord );
src.setBoundsDirty();
}
/**
* Applies a general quadratic transform.
* p <- p + A + B*p + p*C*p
*
* i.e.
* x <- x + a0 + (b00*x + b01*y + b02*z) + x*(c00*x + c01*y + c02*z)
* y <- y + a1 + (b10*x + b11*y + b12*z) + y*(c10*x + c11*y + c12*z)
* z <- z + a2 + (b20*x + b21*y + b22*z) + z*(c20*x + c21*y + c22*z)
*
* @param shape Shape to be changed
* @param A Constant offset
* @param B Linear terms
* @param C Quadratic terms
* @return modified shape if successful; null if not
*/
public static <S extends Shape3D> S quadratic( S shape, Tuple3f A, Matrix3f B, Matrix3f C )
{
Geometry geom = shape.getGeometry();
if ( geom == null )
return ( null );
quadratic( geom, A, B, C );
shape.setGeometry( geom );
return ( shape );
}
private StaticTransform()
{
}
}