/**
* Copyright 2012 Tobias Gierke <tobias.gierke@code-sourcery.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.codesourcery.jasm16.utils;
import java.util.List;
public class LinAlgUtils
{
public static final float DEG_TO_RAD = 0.008726646f; // 0.5*(PI/180)
public static Matrix createMatrix(Vector4 v1,Vector4 v2,Vector4 v3,Vector4 v4)
{
return new Matrix(v1,v2,v3,v4);
}
public static Matrix identity()
{
return Matrix.identity();
}
public static Matrix mult(Matrix m1 , Matrix m2)
{
return m1.multiply( m2 );
}
public static Matrix rotX(float angleInDegrees)
{
final float angleInRad = (float) ( angleInDegrees * 0.5f * ( Math.PI / 180.0f ) );
final float cos = (float) Math.cos( angleInRad );
final float sin = (float) Math.sin( angleInRad );
/*
* 0 0 0 0
* 0 cos -sin 0
* 0 sin cos 0
* 0 0 0 0
*/
Matrix result =
createMatrix( vector( 1, 0 , 0 , 0 ) ,
vector( 0, cos , sin , 0 ) ,
vector( 0 , -sin, cos , 0 ) ,
vector( 0,0,0,1 ) );
return result;
}
/**
* Transforms vertices from another coordinate system to model coordinates.
*
* <p>Note that this method will update the input vertices.</p>
* <p>Coordinate system axis are expected to be columns 0 (x axis),1 (y axis),2 (z axis) in the
* input matrices.</p>
*
* @param vertices vertices to convert
* @param srcSystem the orthonormal basis of the source coordinate system
* @param dstSystem the orthonormal basis of the target coordinate system
*/
public static void convertToCoordinateSystem(List<Vector4> vertices,Matrix dstSystem, Vector4 dstCenter)
{
//
final Vector4 xAxis2 = dstSystem.getColumn( 0 ).normalize();
final Vector4 yAxis2 = dstSystem.getColumn( 1 ).normalize();
final Vector4 zAxis2 = dstSystem.getColumn( 2 ).normalize();
Matrix result2 = new Matrix();
result2.set( 0 , 0 , xAxis2.x() );
result2.set( 1 , 0 , xAxis2.y() );
result2.set( 2 , 0 , xAxis2.z() );
result2.set( 0 , 1 , yAxis2.x() );
result2.set( 1 , 1 , yAxis2.y() );
result2.set( 2 , 1 , yAxis2.z() );
result2.set( 0 , 2 , -zAxis2.x() );
result2.set( 1 , 2 , -zAxis2.y() );
result2.set( 2 , 2 , -zAxis2.z() );
result2.set( 3 , 0 , -1 * xAxis2.dotProduct( dstCenter ) );
result2.set( 3 , 1 , -1 * yAxis2.dotProduct( dstCenter ) );
result2.set( 3 , 2 , zAxis2.dotProduct( dstCenter ) );
result2.set( 3 , 3 , 1 );
result2 = result2.invert();
for ( Vector4 v : vertices ) {
result2.multiplyInPlace( v );
}
}
public static Matrix rotY(float angleInDegrees)
{
final float angleInRad = (float) ( angleInDegrees * 0.5f * ( Math.PI / 180.0f ) );
final float cos = (float) Math.cos( angleInRad );
final float sin = (float) Math.sin( angleInRad );
/*
* cos 0 sin 0
* 0 1 0 0
* -sin 0 cos 0
* 0 0 0 1
*/
Matrix result =
createMatrix( vector( cos, 0 , -sin , 0 ) ,
vector( 0, 1 , 0 , 0 ) ,
vector( sin , 0 , cos , 0 ) ,
vector( 0,0,0,1 ) );
return result;
}
public static Matrix rotZ(float angleInDegrees)
{
final float angleInRad = (float)( angleInDegrees * 0.5f * ( Math.PI / 180.0f ) );
final float cos = (float) Math.cos( angleInRad );
final float sin = (float) Math.sin( angleInRad );
/*
* cos -sin 0 0
* sin cos 0 0
* 0 0 1 0
* 0 0 0 1
*/
Matrix result =
createMatrix( vector( cos, sin , 0 , 0 ) ,
vector( -sin, cos , 0 , 0 ) ,
vector( 0 , 0 , 1 , 0 ) ,
vector( 0,0,0,1 ) );
return result;
}
public static Matrix scalingMatrix(float x , float y , float z ) {
/*
* x 0 0 0
* 0 y 0 0
* 0 0 z 0
* 0 0 0 1
*/
return createMatrix( vector( x , 0 , 0 , 0 ) , vector( 0, y , 0 , 0 ) , vector( 0 , 0, z , 0 ) , vector( 0,0,0, 1 ) );
}
public static Matrix translationMatrix(float x , float y , float z ) {
/*
* 1 0 0 x
* 0 1 0 y
* 0 0 1 z
* 0 0 0 1
*/
return createMatrix( vector( 1 , 0 , 0 , 0 ) , vector( 0, 1 , 0 , 0 ) , vector( 0 , 0, 1 , 0 ) , vector( x,y,z,1 ) );
}
public static Vector4 vector(float x,float y , float z ) {
return new Vector4(x,y,z);
}
public static Vector4 vector(float x,float y , float z ,float w) {
return new Vector4(x,y,z,w);
}
public static Matrix makeFrustum(float left, float right, float bottom, float top, float near,float far)
{
final float[] data = new float[16];
/*
* 2 * near
* -------------- 0
* (right - left)
* 2 * near
* 0 --------------
* top - bottom
*
* 0 0
*
* 0 0
*/
data[0] = 2.0f * near / (right - left);
data[1] = 0.0f;
data[2] = 0.0f;
data[3] = 0.0f;
data[4] = 0.0f;
data[5] = 2.0f * near / (top - bottom);
data[6] = 0.0f;
data[7] = 0.0f;
data[8] = (right + left) / (right - left);
data[9] = (top + bottom) / (top - bottom);
data[10] = ( -(far + near) / (far - near) );
data[11] = -1.0f;
data[12] = 0.0f;
data[13] = 0.0f;
data[14] = (( -2.0f * far * near) / (far - near) );
data[15] = 0.0f;
return new Matrix(data);
}
public static Matrix createOrthoProjection(float field_of_view , float aspect_ratio , float near,float far)
{
final float rad = field_of_view * DEG_TO_RAD;
float size = near * (float) Math.tan( rad / 2.0f);
float left = -size; // left X
float right = size; // right X
float bottom = -size / aspect_ratio; // bottom Y
float top = size / aspect_ratio; // top Y
Matrix result = new Matrix(
vector(2.0f / (right - left), 0, 0, 0 ) ,
vector(0, 2.0f / (top - bottom), 0, 0),
vector(0, 0, -2.0f / (far - near), 0),
vector(-(right + left) / (right - left), -(top + bottom) / (top - bottom), -(far + near) / (far - near), 1 ) );
return result;
}
public static Matrix createPerspectiveProjection(float field_of_view, float aspect_ratio ,float zNear, float zFar)
{
return createPerspectiveProjection2(field_of_view, aspect_ratio, zNear, zFar);
}
private static Matrix createPerspectiveProjection2(float field_of_view, float aspect_ratio ,float zNear, float zFar)
{
float tangent = (float) Math.tan(field_of_view/2 * DEG_TO_RAD); // tangent of half fovY
float height = zNear * tangent; // half height of near plane
float width = height * aspect_ratio; // half width of near plane
// params: left, right, bottom, top, near, far
return makeFrustum(-width, width, -height, height, zNear, zFar);
}
private static Matrix createPerspectiveProjection1(float field_of_view, float aspect_ratio ,float zNear, float zFar)
{
final float rad = field_of_view * DEG_TO_RAD;
float size = zNear * (float) Math.tan( rad / 2.0f);
float xLeft = -size;
float xRight = size;
float yBottom = -size / aspect_ratio;
float yTop = size / aspect_ratio;
return makeFrustum(xLeft, xRight, yBottom,yTop, zNear, zFar);
}
public static Vector4 calcRotation(Vector4 point,Vector4 rotatePoint,Vector4 rotateAngle)
{
final Vector4 d = new Vector4();
d.x( point.x() - rotatePoint.x());
d.y( point.y() - rotatePoint.y() );
d.z( point.z() - rotatePoint.z() );
// X + Y + Z Rotation
// Internet
double x = rotatePoint.x() + Math.cos(rotateAngle.y()) * Math.cos(rotateAngle.z()) * d.x() - Math.cos(rotateAngle.y()) * Math.sin(rotateAngle.z()) * d.y() + Math.sin(rotateAngle.y()) * d.z();
double y = rotatePoint.y() + (Math.cos(rotateAngle.x()) * Math.sin(rotateAngle.z()) + Math.sin(rotateAngle.x()) * Math.sin(rotateAngle.y()) * Math.cos(rotateAngle.z())) * d.x() + (Math.cos(rotateAngle.x()) * Math.cos(rotateAngle.z()) - Math.sin(rotateAngle.x()) * Math.sin(rotateAngle.y()) * Math.sin(rotateAngle.z())) * d.y() - Math.sin(rotateAngle.x()) * Math.cos(rotateAngle.y()) * d.z();
double z = rotatePoint.z() + (Math.sin(rotateAngle.x()) * Math.sin(rotateAngle.z()) - Math.cos(rotateAngle.x()) * Math.sin(rotateAngle.y()) * Math.cos(rotateAngle.z())) * d.x() + (Math.sin(rotateAngle.x()) * Math.cos(rotateAngle.z()) + Math.cos(rotateAngle.x()) * Math.sin(rotateAngle.y()) * Math.sin(rotateAngle.z())) * d.y() + Math.cos(rotateAngle.x()) * Math.cos(rotateAngle.y()) * d.z();
return new Vector4((float) x, (float) y , (float) z );
}
private static Matrix createPerspective2(float fzNear,float fzFar)
{
final float fFrustumScale = 1.0f;
float[] matrixData = new float[ 16 ];
matrixData[0] = fFrustumScale;
matrixData[5] = fFrustumScale;
matrixData[10] = (fzFar + fzNear) / (fzNear - fzFar);
matrixData[14] = (2 * fzFar * fzNear) / (fzNear - fzFar);
matrixData[11] = -1.0f;
return new Matrix( matrixData );
}
public static float findFarestDistance(Vector4 referencePoint,Vector4[] points,int pointsToCompare)
{
float dist = points[0].distanceTo( referencePoint );
for ( int i = 1 ; i < pointsToCompare ; i++)
{
float tmpDist = points[i].distanceTo( referencePoint );
if ( tmpDist > dist ) {
dist = tmpDist;
}
}
return dist;
}
}