mirror of
https://github.com/thes3m/XNI
synced 2024-12-26 13:26:06 +01:00
409 lines
13 KiB
Objective-C
409 lines
13 KiB
Objective-C
//
|
|
// Matrix.m
|
|
// XNI
|
|
//
|
|
// Created by Matej Jan on 9.9.10.
|
|
// Copyright 2010 Retronator. All rights reserved.
|
|
//
|
|
|
|
#import "Matrix.h"
|
|
|
|
#import "Retronator.Xni.Framework.h"
|
|
|
|
@implementation Matrix
|
|
|
|
- (id) initWithMatrixStruct: (MatrixStruct*)matrixStruct {
|
|
if (self = [super init]) {
|
|
data = *matrixStruct;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (id) initWithMatrix: (Matrix*)matrix {
|
|
return [self initWithMatrixStruct:matrix.data];
|
|
}
|
|
|
|
+ (Matrix*) matrixWithStruct: (MatrixStruct*)matrixStruct {
|
|
return [[[Matrix alloc] initWithMatrixStruct:matrixStruct] autorelease];
|
|
}
|
|
|
|
+ (Matrix*) matrixWithMatrix: (Matrix*)matrix {
|
|
return [[[Matrix alloc] initWithMatrix:matrix] autorelease];
|
|
}
|
|
|
|
+ (Matrix*) createTranslationX:(float)xPosition y:(float)yPosition z:(float)zPosition {
|
|
Matrix *matrix = [Matrix identity];
|
|
matrix.data->m41 = xPosition;
|
|
matrix.data->m42 = yPosition;
|
|
matrix.data->m43 = zPosition;
|
|
return matrix;
|
|
}
|
|
|
|
+ (Matrix*) createTranslation:(Vector3*)position {
|
|
Matrix *matrix = [Matrix identity];
|
|
matrix.translation = position;
|
|
return matrix;
|
|
}
|
|
|
|
+ (Matrix*) createScaleUniform:(float)scale {
|
|
Matrix *matrix = [Matrix identity];
|
|
matrix.data->m11 = scale;
|
|
matrix.data->m22 = scale;
|
|
matrix.data->m33 = scale;
|
|
return matrix;
|
|
}
|
|
|
|
+ (Matrix*) createScale:(Vector3 *)scales {
|
|
Matrix *matrix = [Matrix identity];
|
|
matrix.data->m11 = scales.x;
|
|
matrix.data->m22 = scales.y;
|
|
matrix.data->m33 = scales.z;
|
|
return matrix;
|
|
}
|
|
|
|
+ (Matrix *)createScaleX:(float)xScale y:(float)yScale z:(float)zScale {
|
|
Matrix *matrix = [Matrix identity];
|
|
matrix.data->m11 = xScale;
|
|
matrix.data->m22 = yScale;
|
|
matrix.data->m33 = zScale;
|
|
return matrix;
|
|
}
|
|
|
|
+ (Matrix*) createRotationX:(float)radians {
|
|
Matrix *matrix = [Matrix identity];
|
|
matrix.data->m22 = cosf(radians);
|
|
matrix.data->m23 = sinf(radians);
|
|
matrix.data->m32 = - matrix.data->m23;
|
|
matrix.data->m33 = matrix.data->m22;
|
|
return matrix;
|
|
}
|
|
|
|
+ (Matrix*) createRotationY:(float)radians {
|
|
Matrix *matrix = [Matrix identity];
|
|
matrix.data->m11 = cosf(radians);
|
|
matrix.data->m13 = sinf(radians);
|
|
matrix.data->m31 = - matrix.data->m13;
|
|
matrix.data->m33 = matrix.data->m11;
|
|
return matrix;
|
|
}
|
|
|
|
+ (Matrix*) createRotationZ:(float)radians {
|
|
Matrix *matrix = [Matrix identity];
|
|
matrix.data->m11 = cosf(radians);
|
|
matrix.data->m12 = sinf(radians);
|
|
matrix.data->m21 = - matrix.data->m12;
|
|
matrix.data->m22 = matrix.data->m11;
|
|
return matrix;
|
|
}
|
|
|
|
+ (Matrix*) createFromAxis:(Vector3 *)axis angle:(float)angle {
|
|
Vector3 *normalizedAxis = [[Vector3 vectorWithVector:axis] normalize];
|
|
|
|
float c = cosf(angle);
|
|
float s = sinf(angle);
|
|
float x = normalizedAxis.x;
|
|
float y = normalizedAxis.y;
|
|
float z = normalizedAxis.z;
|
|
|
|
Matrix *matrix = [Matrix zero];
|
|
matrix.data->m11 = (x * x) * (1 - c) + c;
|
|
matrix.data->m12 = (y * x) * (1 - c) + (z * s);
|
|
matrix.data->m13 = (x * z) * (1 - c) - (y * s);
|
|
matrix.data->m21 = (x * y) * (1 - c) - (z * s);
|
|
matrix.data->m22 = (y * y) * (1 - c) + c;
|
|
matrix.data->m23 = (y * z) * (1 - c) + (x * s);
|
|
matrix.data->m31 = (x * z) * (1 - c) + (y * s);
|
|
matrix.data->m32 = (y * z) * (1 - c) - (x * s);
|
|
matrix.data->m33 = (z * z) * (1 - c) + c;
|
|
matrix.data->m44 = 1;
|
|
return matrix;
|
|
}
|
|
|
|
+ (Matrix*) createFromQuaternion:(Quaternion *)quaternion {
|
|
Quaternion *normalizedQuaternion = [[Quaternion quaternionWithQuaternion:quaternion] normalize];
|
|
|
|
float x = normalizedQuaternion.x;
|
|
float y = normalizedQuaternion.y;
|
|
float z = normalizedQuaternion.z;
|
|
float w = normalizedQuaternion.w;
|
|
|
|
Matrix *matrix = [Matrix zero];
|
|
matrix.data->m11 = 1 - 2 * ( y * y + z * z );
|
|
matrix.data->m12 = 2 * ( x * y - z * w );
|
|
matrix.data->m13 = 2 * ( x * z + y * w );
|
|
matrix.data->m21 = 2 * ( x * y + z * w );
|
|
matrix.data->m22 = 1 - 2 * ( x * x + z * z );
|
|
matrix.data->m23 = 2 * ( y * z - x * w );
|
|
matrix.data->m31 = 2 * ( x * z - y * w );
|
|
matrix.data->m32 = 2 * ( y * z + x * w );
|
|
matrix.data->m33 = 1 - 2 * ( x * x + y * y );
|
|
matrix.data->m44 = 1;
|
|
return matrix;
|
|
}
|
|
|
|
+ (Matrix*) createLookAtFrom:(Vector3*)position to:(Vector3*)target up:(Vector3*)up {
|
|
Vector3 *z = [[Vector3 subtract:position by:target] normalize];
|
|
Vector3 *x = [[Vector3 crossProductOf:up with:z] normalize];
|
|
Vector3 *y = [Vector3 crossProductOf:z with:x];
|
|
Matrix *matrix = [Matrix zero];
|
|
// First column
|
|
matrix.data->m11 = x.x;
|
|
matrix.data->m21 = x.y;
|
|
matrix.data->m31 = x.z;
|
|
// Second column
|
|
matrix.data->m12 = y.x;
|
|
matrix.data->m22 = y.y;
|
|
matrix.data->m32 = y.z;
|
|
// Third column
|
|
matrix.data->m13 = z.x;
|
|
matrix.data->m23 = z.y;
|
|
matrix.data->m33 = z.z;
|
|
// Translation
|
|
matrix.data->m41 = -[Vector3 dotProductOf:x with:position];
|
|
matrix.data->m42 = -[Vector3 dotProductOf:y with:position];
|
|
matrix.data->m43 = -[Vector3 dotProductOf:z with:position];
|
|
matrix.data->m44 = 1;
|
|
return matrix;
|
|
}
|
|
|
|
+ (Matrix*) createOrthographicWithWidth:(float)width height:(float)height
|
|
zNearPlane:(float)zNearPlane zFarPlane:(float)zFarPlane {
|
|
|
|
Matrix *matrix = [Matrix zero];
|
|
matrix.data->m11 = 2 / width;
|
|
matrix.data->m22 = 2 / height;
|
|
matrix.data->m33 = 1 / (zNearPlane - zFarPlane);
|
|
matrix.data->m43 = zNearPlane / (zNearPlane - zFarPlane);
|
|
matrix.data->m44 = 1;
|
|
return matrix;
|
|
}
|
|
|
|
+ (Matrix*) createOrthographicOffCenterWithLeft:(float)left right:(float)right
|
|
bottom:(float)bottom top:(float)top
|
|
zNearPlane:(float)zNearPlane zFarPlane:(float)zFarPlane {
|
|
|
|
Matrix *matrix = [Matrix zero];
|
|
matrix.data->m11 = 2 / (right - left);
|
|
matrix.data->m22 = 2 / (top - bottom);
|
|
matrix.data->m33 = 1 / (zNearPlane - zFarPlane);
|
|
matrix.data->m41 = (left + right) / (left - right);
|
|
matrix.data->m42 = (top + bottom) / (bottom - top);
|
|
matrix.data->m43 = zNearPlane / (zNearPlane - zFarPlane);
|
|
matrix.data->m44 = 1;
|
|
return matrix;
|
|
}
|
|
|
|
+ (Matrix*) createPerspectiveWithWidth:(float)width height:(float)height
|
|
nearPlaneDistance:(float)nearPlaneDistance farPlaneDistance:(float)farPlaneDistance {
|
|
|
|
Matrix *matrix = [Matrix zero];
|
|
matrix.data->m11 = (2 * nearPlaneDistance) / width;
|
|
matrix.data->m22 = (2 * nearPlaneDistance) / height;
|
|
matrix.data->m33 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
|
|
matrix.data->m34 = -1;
|
|
matrix.data->m43 = nearPlaneDistance * farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
|
|
return matrix;
|
|
}
|
|
|
|
+ (Matrix*) createPerspectiveFieldOfView:(float)fieldOfView aspectRatio:(float)aspectRatio
|
|
nearPlaneDistance:(float)nearPlaneDistance farPlaneDistance:(float)farPlaneDistance {
|
|
|
|
float yScale = 1.0f / tanf(fieldOfView / 2.0f);
|
|
float xScale = yScale / aspectRatio;
|
|
Matrix *matrix = [Matrix zero];
|
|
matrix.data->m11 = xScale;
|
|
matrix.data->m22 = yScale;
|
|
matrix.data->m33 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
|
|
matrix.data->m34 = -1;
|
|
matrix.data->m43 = nearPlaneDistance * farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
|
|
return matrix;
|
|
}
|
|
|
|
+ (Matrix*) createPerspectiveOffCenterWithLeft:(float)left right:(float)right
|
|
bottom:(float)bottom top:(float)top
|
|
nearPlaneDistance:(float)nearPlaneDistance farPlaneDistance:(float)farPlaneDistance {
|
|
|
|
Matrix *matrix = [Matrix zero];
|
|
matrix.data->m11 = (2 * nearPlaneDistance) / (right - left);
|
|
matrix.data->m22 = (2 * nearPlaneDistance) / (top - bottom);
|
|
matrix.data->m31 = (2 * nearPlaneDistance) / (left + right) / (right - left);
|
|
matrix.data->m31 = (2 * nearPlaneDistance) / (top + bottom) / (top - bottom);
|
|
matrix.data->m33 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
|
|
matrix.data->m34 = -1;
|
|
matrix.data->m43 = nearPlaneDistance * farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
|
|
return matrix;
|
|
}
|
|
|
|
+ (Matrix*) createWorldAtPosition:(Vector3 *)position forward:(Vector3 *)forward up:(Vector3 *)up {
|
|
Vector3 *z = [[Vector3 negate:forward] normalize];
|
|
Vector3 *x = [[Vector3 crossProductOf:up with:z] normalize];
|
|
Vector3 *y = [Vector3 crossProductOf:z with:x];
|
|
Matrix *matrix = [Matrix identity];
|
|
matrix.right = x;
|
|
matrix.up = y;
|
|
matrix.backward = z;
|
|
matrix.translation = position;
|
|
return matrix;
|
|
}
|
|
|
|
// PROPERTIES
|
|
|
|
- (MatrixStruct*) data {return &data;}
|
|
|
|
// Main rows
|
|
|
|
- (Vector3 *) right {return [Vector3 vectorWithX:data.m11 y:data.m12 z:data.m13];}
|
|
- (void) setRight:(Vector3 *)value {data.m11 = value.x; data.m12 = value.y; data.m13 = value.z;}
|
|
|
|
- (Vector3 *) up {return [Vector3 vectorWithX:data.m21 y:data.m22 z:data.m23];}
|
|
- (void) setUp:(Vector3 *)value {data.m21 = value.x; data.m22 = value.y; data.m23 = value.z;}
|
|
|
|
- (Vector3 *) backward {return [Vector3 vectorWithX:data.m31 y:data.m32 z:data.m33];}
|
|
- (void) setBackward:(Vector3 *)value {data.m31 = value.x; data.m32 = value.y; data.m33 = value.z;}
|
|
|
|
- (Vector3 *) translation {return [Vector3 vectorWithX:data.m41 y:data.m42 z:data.m43];}
|
|
- (void) setTranslation:(Vector3 *)value {data.m41 = value.x; data.m42 = value.y; data.m43 = value.z;}
|
|
|
|
// Negative rows
|
|
|
|
- (Vector3 *) left {return [Vector3 vectorWithX:-data.m11 y:-data.m12 z:-data.m13];}
|
|
- (void) setLeft:(Vector3 *)value {data.m11 = -value.x; data.m12 = -value.y; data.m13 = -value.z;}
|
|
|
|
- (Vector3 *) down {return [Vector3 vectorWithX:-data.m21 y:-data.m22 z:-data.m23];}
|
|
- (void) setDown:(Vector3 *)value {data.m21 = -value.x; data.m22 = -value.y; data.m23 = -value.z;}
|
|
|
|
- (Vector3 *) forward {return [Vector3 vectorWithX:-data.m31 y:-data.m32 z:-data.m33];}
|
|
- (void) setForward:(Vector3 *)value {data.m31 = -value.x; data.m32 = -value.y; data.m33 = -value.z;}
|
|
|
|
// METHODS
|
|
|
|
+ (Matrix*) negate:(Matrix*)value {
|
|
Matrix *result = [Matrix matrixWithMatrix:value];
|
|
[result negate];
|
|
return result;
|
|
}
|
|
|
|
+ (Matrix*) transpose:(Matrix*)value {
|
|
MatrixStruct resultData = *value.data;
|
|
MatrixTranspose(&resultData);
|
|
return [Matrix matrixWithStruct:&resultData];
|
|
}
|
|
|
|
+ (Matrix*) invert:(Matrix*)value {
|
|
MatrixStruct resultData = *value.data;
|
|
MatrixInvert(&resultData);
|
|
return [Matrix matrixWithStruct:&resultData];
|
|
}
|
|
|
|
+ (Matrix*) add:(Matrix*)value1 to:(Matrix*)value2 {
|
|
MatrixStruct resultData;
|
|
MatrixAdd(value1.data, value2.data, &resultData);
|
|
return [Matrix matrixWithStruct:&resultData];
|
|
}
|
|
|
|
+ (Matrix*) subtract:(Matrix*)value1 by:(Matrix*)value2{
|
|
MatrixStruct resultData;
|
|
MatrixSubtract(value1.data, value2.data, &resultData);
|
|
return [Matrix matrixWithStruct:&resultData];
|
|
}
|
|
|
|
+ (Matrix*) multiply:(Matrix*)value1 byScalar:(float)scaleFactor{
|
|
MatrixStruct resultData;
|
|
MatrixMultiplyScalar(value1.data, scaleFactor, &resultData);
|
|
return [Matrix matrixWithStruct:&resultData];
|
|
}
|
|
|
|
+ (Matrix*) multiply:(Matrix*)value1 by:(Matrix*)value2{
|
|
MatrixStruct resultData;
|
|
MatrixMultiply(value1.data, value2.data, &resultData);
|
|
return [Matrix matrixWithStruct:&resultData];
|
|
}
|
|
|
|
+ (Matrix*) divide:(Matrix*)value1 byScalar:(float)divider{
|
|
MatrixStruct resultData;
|
|
MatrixDivideScalar(value1.data, divider, &resultData);
|
|
return [Matrix matrixWithStruct:&resultData];
|
|
}
|
|
|
|
+ (Matrix*) divide:(Matrix*)value1 by:(Matrix*)value2{
|
|
MatrixStruct resultData;
|
|
MatrixDivide(value1.data, value2.data, &resultData);
|
|
return [Matrix matrixWithStruct:&resultData];
|
|
}
|
|
|
|
- (float) determinant {
|
|
return MatrixDeterminant(self.data);
|
|
}
|
|
|
|
- (Matrix*) negate {
|
|
MatrixNegate(self.data);
|
|
return self;
|
|
}
|
|
|
|
- (Matrix*) set:(Matrix *)value {
|
|
data = *value.data;
|
|
return self;
|
|
}
|
|
|
|
- (Matrix*) add:(Matrix*)value {
|
|
MatrixAdd(self.data, value.data, self.data);
|
|
return self;
|
|
}
|
|
|
|
- (Matrix*) subtract:(Matrix*)value {
|
|
MatrixSubtract(self.data, value.data, self.data);
|
|
return self;
|
|
}
|
|
|
|
- (Matrix*) multiplyByScalar:(float)scaleFactor {
|
|
MatrixMultiplyScalar(self.data, scaleFactor, self.data);
|
|
return self;
|
|
}
|
|
|
|
- (Matrix*) multiplyBy:(Matrix*)value {
|
|
MatrixMultiply(self.data, value.data, self.data);
|
|
return self;
|
|
}
|
|
|
|
- (Matrix*) divideByScalar:(float)divider {
|
|
MatrixDivideScalar(self.data, divider, self.data);
|
|
return self;
|
|
}
|
|
|
|
- (Matrix*) divideBy:(Matrix*)value {
|
|
MatrixDivide(self.data, value.data, self.data);
|
|
return self;
|
|
}
|
|
|
|
- (id) copyWithZone:(NSZone *)zone {
|
|
return [[Matrix allocWithZone:zone] initWithMatrixStruct:&data];
|
|
}
|
|
|
|
- (BOOL) equals:(Matrix*)matrix {
|
|
if (!matrix) return NO;
|
|
return matrix.data->m11 == data.m11 && matrix.data->m12 == data.m12 && matrix.data->m13 == data.m13 && matrix.data->m14 == data.m14 &&
|
|
matrix.data->m21 == data.m21 && matrix.data->m22 == data.m22 && matrix.data->m23 == data.m23 && matrix.data->m24 == data.m24 &&
|
|
matrix.data->m31 == data.m31 && matrix.data->m32 == data.m32 && matrix.data->m33 == data.m33 && matrix.data->m34 == data.m34 &&
|
|
matrix.data->m41 == data.m41 && matrix.data->m42 == data.m42 && matrix.data->m43 == data.m43 && matrix.data->m44 == data.m44;
|
|
}
|
|
|
|
- (BOOL) isEqual:(id)object {
|
|
if ([object isKindOfClass:[Matrix class]]) {
|
|
return [self equals:object];
|
|
}
|
|
return NO;
|
|
}
|
|
|
|
// CONSTANTS
|
|
|
|
+ (id) zero {
|
|
MatrixStruct matrixStruct = MatrixMake(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
return [Matrix matrixWithStruct:&matrixStruct];
|
|
}
|
|
+ (id) identity {
|
|
MatrixStruct matrixStruct = MatrixMake(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
|
return [Matrix matrixWithStruct:&matrixStruct];
|
|
}
|
|
|
|
@end
|