Skip to content

Instantly share code, notes, and snippets.

@palra
Created January 12, 2015 23:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save palra/94f967509bbe5cefadae to your computer and use it in GitHub Desktop.
Save palra/94f967509bbe5cefadae to your computer and use it in GitHub Desktop.
CasGL
#include "CasGL.h"
#include "Matrices.h"
#include <mathf.h>
Matrix4 GL_ProjectionMatrixRH(float width, float height, float near, float far)
{
Matrix4 mat;
mat[0] = (2*near) / width;
mat[5] = (2*near) / height;
mat[10] = far / (near - far);
mat[11] = (near * far) / (near - far);
mat[14] = -1;
mat[15] = 0;
return mat;
}
Matrix4 GL_ProjectionMatrixFovRH(float fovY, float ratio, float near, float far)
{
Matrix4 mat;
mat[5] = 1 / tanf(0.5f * fovY);
mat[0] = mat[5] / ratio;
mat[10] = far / (near - far);
mat[11] = (near * far) / (near - far);
mat[14] = -1;
mat[15] = 0;
return mat;
}
void GL_LookAtToAxes(
const Vector3& position, const Vector3& target,
Vector3& left, Vector3& up, Vector3& forward)
{
forward = target - position;
forward.normalize();
if(fabs(forward.x) < EPSILON && fabs(forward.z) < EPSILON)
{
if(forward.y > 0)
up = Vector3(0, 0, -1);
else
up = Vector3(0, 0, 1);
} else
up = Vector3(0, 1, 0);
left = up.cross(forward);
left.normalize();
up = forward.cross(left);
up.normalize();
}
void GL_LookAtToAxes(
const Vector3& position, const Vector3& target, const Vector3& upDir,
Vector3& left, Vector3& up, Vector3& forward)
{
forward = target-position;
forward.normalize();
left = upDir.cross(forward);
left.normalize();
up = forward.cross(left);
up.normalize();
}
Matrix4 GL_LookAtMatrixRH(const Vector3 eye, const Vector3 target, const Vector3 up)
{
Vector3 zaxis = (eye - target).normalize();
Vector3 xaxis = up.cross(zaxis).normalize();
Vector3 yaxis = zaxis.cross(xaxis);
Matrix4 mat(
xaxis.x, xaxis.y, xaxis.z, 0, // 1st column
yaxis.x, yaxis.y, yaxis.z, 0, // 2nd column
zaxis.x, zaxis.y, zaxis.z, 0, // 3rd column
-xaxis.dot(eye) , -yaxis.dot(eye), -zaxis.dot(eye), 1 // 4th column
);
return mat;
}
#pragma once
#include "Matrices.h"
Matrix4 GL_ProjectionMatrixRH(float width, float height, float near, float far);
Matrix4 GL_ProjectionMatrixFovRH(float fovY, float ratio, float near, float far);
void GL_LookAtToAxes(const Vector3& position, const Vector3& target,Vector3& left, Vector3& up, Vector3& forward);
void GL_LookAtToAxes(const Vector3& position, const Vector3& target, const Vector3& upDir,Vector3& left, Vector3& up, Vector3& forward);
Matrix4 GL_LookAtMatrixRH(const Vector3 eye, const Vector3 target, const Vector3 up);
/***********************************/
/** Easy Coding **/
/**Category : Snippets Collection **/
/**@author Eiyeron **/
/**@contact eiyeron@gmail.com **/
/**@file ECode.c **/
/**Version : 1.11 **/
/**Date of creation : 06/28/2011 **/
/***********************************/
#include "ECode.h"
/******************************/
/** Dependencies management **/
/******************************/
#ifdef EASY_ALL
#define EASY_MODEL
#define EASY_STRING
#define EASY_2STR
#define EASY_2NUM
#define EASY_2HEX
#define EASY_BITS
#define EASY_KEYS
#define EASY_OTHERS
#endif
#ifdef EASY_MODEL
#define EASY_ISEMULATOR
#define EASY_ISG35P
#define EASY_ISG75
#define EASY_ISG85
#define EASY_ISG85SD
#define EASY_ISG95
#define EASY_MODELDETECTOR
#define EASY_HASSD
#endif
#ifdef EASY_STRING
#define EASY_TOLOWER
#define EASY_TOUPPER
#define EASY_STRMIRROR
#define EASY_STRROTATE
#define EASY_PRINTF
#define EASY_PRINTN
#endif
#ifdef EASY_2STR
#define EASY_CHAR2STR
#define EASY_UCHAR2STR
#define EASY_INT2STR
#define EASY_UINT2STR
#define EASY_FLOAT2STR
#endif
#ifdef EASY_2NUM
#define EASY_STR2CHAR
#define EASY_STR2UCHAR
#define EASY_STR2INT
#define EASY_STR2UINT
#endif
#ifdef EASY_2HEX
#define EASY_CHAR2HEX
#define EASY_INT2HEX
#endif
#ifdef EASY_BITS
#define EASY_READ_BIT_CHAR
#define EASY_UP_BIT_CHAR
#define EASY_DOWN_BIT_CHAR
#define EASY_INVERSE_BIT_CHAR
#define EASY_READ_BIT_INT
#define EASY_UP_BIT_INT
#define EASY_DOWN_BIT_INT
#define EASY_INVERSE_BIT_INT
#endif
#ifdef EASY_KEYS
#define EASY_KEY_DOWN
#define EASY_KEY_UP
#define EASY_ANY_KEY
#endif
#ifdef EASY_OTHERS
#define EASY_INPUT
#define EASY_NUMARRAY_CHAR
#define EASY_NUMARRAY_INT
#endif
#ifdef EASY_KEY_UP
#define EASY_KEY_DOWN
#endif
#ifdef EASY_FLOAT2STR
#define EASY_INT2STR
#endif
#ifdef EASY_INPUT
#include "fxlib.h"
#endif
#ifdef EASY_PRINTF
#include "fxlib.h"
#endif
#ifdef EASY_PRINTN
#include "fxlib.h"
#endif
/***************/
/** Functions **/
/***************/
static int SysCallCode[] = {0xD201422B,0x60F20000,0x80010070};
static int (*SysCall)( int R4, int R5, int R6, int R7, int FNo ) = (void*)&SysCallCode; // Elles sont en static, car je ne vais pas encore publier la liste des syscalls "utiles"
#ifdef EASY_ISEMULATOR
char isEmulator()
{
return !( *(int*)0x80000300 );
}
#endif
#ifdef EASY_ISG35P
char isG35p75()
{
return ( *(int*)0x80000300 == 0x33363246 ) && ( *(char*)0x8024FEE0 == 0xB4393341);
}
#endif
#ifdef EASY_ISG75
char isG75()
{
return ( *(int*)0x80000300 == 0xFAE0FB2C && *(char*)0x8024FEE0 == 0x4BC8053F);
}
#endif
#ifdef EASY_ISG85
char isG85()
{
return ( *(int*)0x80000300 == 0x80005D7C );
}
#endif
#ifdef EASY_ISG85SD
char isG85SD()
{
return *(int*)((*SysCall)(0, 0, 0, 0, 1128));
}
#endif
#ifdef EASY_ISG95
char isG95()
{
return ( *(int*)0x80000300 == 0x34393342 );
}
#endif
#ifdef EASY_MODELDETECTOR
Model modelDetector()
{
int model = *(int*)0x80000300;
switch(model)
{
case 0 :
return EMULATOR;
break;
case 0x33363246:
if ( *(int*)0x8024FEE0 == 0xB4393341)
return G35;
else return UNDEFINED;
break;
case 0x34393542:
if((int*)((*SysCall)(0, 0, 0, 0, 1128))) return G75;
else return G75;
break;
case 0x80005D7C :
if((int*)((*SysCall)(0, 0, 0, 0, 1128))) return G85SD;
else return G85;
break;
case 0x34393342 :
return G95;
break;
default :
return UNDEFINED;
break;
}
}
#endif
#ifdef EASY_HASSD
char hasSD()
{
return ( *(char*)((*SysCall)(0, 0, 0, 0, 1128)) );
}
#endif
#ifdef EASY_TOLOWER/** OK */
unsigned char* toLower(unsigned char* str)
{
int i;
for(i=0; str[i] != '\0'; i++)
{
if(str[i] >= 'A' && str[i] <= 'Z')
str[i] += 32;
}
return str;
}
#endif
#ifdef EASY_TOUPPER/** OK */
unsigned char* toUpper(unsigned char* str)
{
int i;
for(i=0; str[i] != '\0' ; i++)
{
if(str[i] >= 'a' && str[i] <= 'z')
str[i] -= 32;
}
return str;
}
#endif
#ifdef EASY_STRMIRROR/** OK */
unsigned char* strMirror(unsigned char* str)
{
int i, len;
unsigned char tmp;
for(len=0; str[len]!= '\0' ; len++);
for(i=0; i< (int) len/2; i++)
{
tmp = str[len-i-1];
str[len-i-1] = str[i];
str[i] = tmp;
}
return str;
}
#endif
#ifdef EASY_STRROTATE /** OK */
unsigned char* strRotate(unsigned char* str, char mov)
{
int i, len;
unsigned char tmp;
for(len=0; str[len]!= '\0' ; len++);
mov= mov%len;
if(mov < 0)
mov += len;
if(mov == 0)
return str;
while(mov)
{
tmp = str[len-1];
for(i=len-1;i>0;i--)
str[i] = str[i-1];
str[0] = tmp;
mov--;
}
return str;
}
#endif
#ifdef EASY_PRINTF/** OK */
/*void printf(unsigned char x, unsigned char y, unsigned char* str, int mode)
{
locate(x,y);
switch(mode)
{
case 0:
Print(str);
return;
case 1:
PrintRev(str);
return;
}
}*/
void printf(unsigned char x, unsigned char y, unsigned char* str, char mode)
{
locate(x,y);
if(mode)
PrintRev(str);
else
Print(str);
}
#endif
#ifdef EASY_PRINTN/** OK */
void printn(unsigned char x, unsigned char y, int n, char mode)
{
unsigned char c[12];
intToStr(c, n);
locate(x,y);
if(mode)
PrintRev(c);
else
Print(c);
}
#endif
#ifdef EASY_INT2STR/** OK */
unsigned char* intToStr(unsigned char* c, int n)
{
if(n==0)
{
c[0] = '0';
c[1] = 0;
}
else
{
int i, l=0;
if(n<0)
{
c[0] = '-';
n = abs(n);
l++;
}
for(i=n ; i ; i/=10)
l++;
c[l] = 0;
for(i=n ; i ; i/=10)
c[--l] = i%10+'0';
}
return c;
}
#endif
#ifdef EASY_UINT2STR/** OK */
unsigned char* uintToStr(unsigned char* c, unsigned int n)
{
if(n==0)
{
c[0] = '0';
c[1] = 0;
}
else
{
unsigned int i, l=0;
for(i=n ; i ; i/=10)
l++;
c[l] = 0;
for(i=n ; i ; i/=10)
c[--l] = i%10+'0';
}
return c;
}
#endif
#ifdef EASY_CHAR2STR/** OK */
unsigned char* charToStr(unsigned char* c, char n)
{
if(n==0)
{
c[0] = '0';
c[1] = 0;
}
else
{
int i, l=0;
if(n<0)
{
c[0] = '-';
n = abs(n);
l++;
}
for(i=n ; i ; i/=10)
l++;
c[l] = 0;
for(i=n ; i ; i/=10)
c[--l] = i%10+'0';
}
return c;
}
#endif
#ifdef EASY_UCHAR2STR/** OK */
unsigned char* ucharToStr(unsigned char* c, unsigned char n)
{
if(n==0)
{
c[0] = '0';
c[1] = 0;
}
else
{
int i, l=0;
/*if(n<0)
{
c[0] = '-';
n = abs(n);
l++;
}*/
for(i=n ; i ; i/=10)
l++;
c[l] = 0;
for(i=n ; i ; i/=10)
c[--l] = i%10+'0';
}
return c;
}
#endif
#ifdef EASY_FLOAT2STR
unsigned char* floatToStr(unsigned char* c, float f, int precision)
{
int i, n=0, index = 0;
if(f<0)
{
f *=-1;
c[0] = '-';
index++;
}
i = f;
intToStr((unsigned char*)((int)c+index), i);
while(c[index])
index++;
if(f-i) {
c[index] = '.';
index++;
i = f = (f-i)*10;
while(f && n<precision) {
c[index] = i;
index++;
n++;
i = f = (f-i)*10;
}
c[index+1] = 0;
}
return c;
}
#endif
#ifdef EASY_STR2CHAR
char strToChar(unsigned char* c)
{
int i, start = 0;
char n = 0;
if(c[0] == '-')
start++;
for(i=start; c[i]; i++)
{
if(c[i]<='9' && c[i] >= '0')
n = n*10+c[i] - '0';
}
if(start)
n *= -1;
return n;
}
#endif
#ifdef EASY_STR2UCHAR
unsigned char strToUchar(unsigned char* c)
{
int i = 0;
char n = 0;
for(i=0; c[i]; i++)
{
if(c[i]<='9' && c[i] >= '0')
n = n*10+c[i] - '0';
}
return n;
}
#endif
#ifdef EASY_STR2INT
int strToInt(unsigned char* c)
{
int i,n = 0, start = 0;
if(c[0] == '-')
start++;
for(i=start; c[i]; i++)
{
if(c[i]<='9' && c[i] >= '0')
n = n*10+c[i] - '0';
}
if(start)
n *= -1;
return n;
}
#endif
#ifdef EASY_STR2UINT
unsigned int strToUint(unsigned char* c)
{
int i,n = 0;
for(i=0; c[i]; i++)
{
if(c[i]<='9' && c[i] >= '0')
n = n*10+c[i] - '0';
}
return n;
}
#endif
#ifdef EASY_CHAR2HEX
char* charToHex(char* result, unsigned char hex) // Needs an 3-char array ("xx\0")
{
char HEX1=hex/16;
char HEX2=hex%16;
if (HEX1<=9)
HEX1+='0';
else
HEX1=HEX1-10+'a';
if (HEX2<=9)
HEX2+='0';
else
HEX2=HEX2-10+'a';
result[0] = HEX1;
result[1] = HEX2;
result[2] = '\0';
return result;
}
#endif
#ifdef EASY_INT2HEX
char* intToHex(char* result, unsigned int hex) // Needs an 9-char array ("xxxxxxxx\0")
{
int i;
for(i=0 ; i<8 ; i++)
{
result[7-i] = (hex&15) + ((hex&15)>9 ? 'A'-10 : '0');
hex >>= 4;
}
result[8] = '\0';
return result;
}
#endif
#ifdef EASY_READ_BIT_CHAR
char readBit_char(char num, char index)
{
return !(num & 1<< (7 - index)) ==0;
}
#endif
#ifdef EASY_INVERSE_BIT_CHAR
char inverseBit_char(char num, char index)
{
return num ^ 1<<7-index;
}
#endif
#ifdef EASY_UP_BIT_CHAR
char upBit_char(char num, char index)
{
return num | 1<<7-index;
}
#endif
#ifdef EASY_DOWN_BIT_CHAR
char downBit_char(char num, char index)
{
return num & (~(1<<(7-index)));
}
#endif
#ifdef EASY_READ_BIT_INT
char readBit_int(int num, char index)
{
return (num & 1 << 31 - index)& 1;
}
#endif
#ifdef EASY_INVERSE_BIT_INT
int inverseBit_int(int num, char index)
{
return num ^ 1<<31-index;
}
#endif
#ifdef EASY_UP_BIT_INT
int upBit_int(int num, char index)
{
return num | 1<<31-index;
}
#endif
#ifdef EASY_DOWN_BIT_INT
int downBit_int(int num, char index)
{
return num & (~1<<31-index);
}
#endif
static void delay( void ) // Cette fonction n'est utilisée que pour KeyDown/Up, et elle n'est absolument pas utile ailleurs. D'où le static.
{
unsigned char i;
for (i=0;i<5;i++);
}
#ifdef EASY_KEY_DOWN
unsigned char KeyDown( unsigned char code)
{
int result=0;
short*PORTB_CTRL=(void*)0xA4000102;
short*PORTM_CTRL=(void*)0xA4000118;
char*PORTB=(void*)0xA4000122;
char*PORTM=(void*)0xA4000138;
char*PORTA=(void*)0xA4000120;
short smask;
char cmask;
unsigned char column, row;
column = code>>4;
row = code &0x0F;
smask = 0x0003 << (( row %8)*2);
cmask = ~( 1 << ( row %8) );
if ( row <8)
{
// configure port B as input, except for the "row to check"-bit, which has to be an output.
*PORTB_CTRL = 0xAAAA ^ smask;
// configure port M as input; port M is inactive with row < 8
*PORTM_CTRL = (*PORTM_CTRL & 0xFF00 ) | 0x00AA;
delay();
*PORTB = cmask; // set the "row to check"-bit to 0 on port B
*PORTM = (*PORTM & 0xF0 ) | 0x0F; // port M is inactive with row < 8
}
else
{
*PORTB_CTRL = 0xAAAA; // configure port B as input; port B is inactive with row >= 8
// configure port M as input, except for the "row to check"-bit, which has to be an output.
*PORTM_CTRL = ((*PORTM_CTRL & 0xFF00 ) | 0x00AA) ^ smask;
delay();
*PORTB = 0xFF; // port B is inactive with row >= 8 (all to 1)
*PORTM = (*PORTM & 0xF0 ) | cmask; // set the "row to check"-bit to 0
};
delay();
result = (~(*PORTA))>>column&1; // a pressed key in the row-to-check draws the corresponding bit to 0
delay();
*PORTB_CTRL = 0xAAAA;
*PORTM_CTRL = (*PORTM_CTRL & 0xFF00 ) | 0x00AA;
delay();
*PORTB_CTRL = 0x5555;
*PORTM_CTRL = (*PORTM_CTRL & 0xFF00 ) | 0x0055;
delay();
return result;
}
#endif
#ifdef EASY_KEY_UP
unsigned char KeyUp(unsigned char code)
{
return !(KeyDown(code));
}
#endif
#ifdef EASY_ANY_KEY
unsigned char AnyKey()
{
return *((unsigned char*)0xA4000120)!=0xFF;
}
#endif
#ifdef EASY_INPUT
char* input(char* c, int x, int y, int longueur, char nb)
{
int i, key, curseur=0;
char lettre;
locate(x, y);
Print("[");
locate(x+longueur+1, y);Print("]");
while(1)
{
locate(x+1, y);
Print(c);
if(strlen(c)<longueur) Print(" ");
Bdisp_DrawLineVRAM((x+curseur)*6, (y-1)*8, (x+curseur)*6, (y-1)*8+6);
Bdisp_DrawLineVRAM((x+curseur)*6+1, (y-1)*8, (x+curseur)*6+1, (y-1)*8+6);
lettre=0;
GetKey(&key);
switch(key)
{
case KEY_CTRL_LEFT: if(curseur) curseur--; break;
case KEY_CTRL_RIGHT: if(c[curseur]) curseur++; break;
case KEY_CTRL_DEL:
if(curseur)
{
for(i=curseur ; i<longueur ; i++)
c[i-1] = c[i];
locate(x+curseur+1, y);Print(" ");
curseur--;
}
else
{
for(i=0 ; c[i] ; i++)
c[i] = c[i+1];
}
break;
case KEY_CTRL_EXIT: c[0] = 0; return c;
case KEY_CTRL_QUIT: c[0] = 0; return c;
case KEY_CTRL_EXE: return c;
case KEY_CHAR_PLUS: lettre='+'; break;
case KEY_CHAR_MINUS: lettre='-'; break;
case KEY_CHAR_POW: lettre='^'; break;
case KEY_CTRL_XTT: lettre='X'; break;
default:
if(nb)
{
if(key>='0' && key<='9')
lettre=key;
}
else if(key>0 && key<256)
lettre=key;
}
if(lettre && curseur<longueur)
{
for(i=longueur-1 ; i>=curseur ; i--)
c[i] = c[i-1];
c[curseur] = lettre;
curseur++;
}
}
}
#endif
#ifdef EASY_NUMARRAY_CHAR
int numArray_char(char* arr)
{
return sizeof(arr);
}
#endif
#ifdef EASY_NUMARRAY_INT
int numArray_int(char* arr)
{
return sizeof(arr)/4;
}
#endif
/***********************************/
/** Easy Coding **/
/**Category : Snippets Collection **/
/**@author Eiyeron **/
/**@contact eiyeron@gmail.com **/
/**@file ECode.h **/
/**Version : 1.11 **/
/**Date of creation : 06/28/2011 **/
/***********************************/
#ifndef EASYCODE
#define EASY_CODE
/****************************************************/
/** uncomment #define EASY_of functions you want to use **/
/****************************************************/
#define EASY_ALL //define all functions
// #define EASY_MODEL
// #define EASY_STRING
// #define EASY_2STR
// #define EASY_2NUM
// #deinfe EASY_2HEX
// #define EASY_BITS
// #define EASY_KEYS
// #define EASY_OTHERS
/**MODEL DETECTION**/
// #define EASY_ISEMULATOR
// #define EASY_ISG35P
// #define EASY_ISG75
// #define EASY_ISG85
// #define EASY_ISG85SD
// #define EASY_ISG95
// #define EASY_MODELDETECTOR
/**STRING MANIUPLATION**/
// #define EASY_TOLOWER
// #define EASY_TOUPPER
// #define EASY_STRMIRROR
// #define EASY_STRROTATE
// #define EASY_PRINTF
// #define EASY_PRINTN
/**TO STRING**/
// #define EASY_CHAR2STR
// #define EASY_UCHAR2STR
// #define EASY_INT2STR
// #define EASY_UINT2STR
// #define EASY_FLOAT2STR
/**TO NUMBER**/
// #define EASY_STR2CHAR
// #define EASY_STR2UCHAR
// #define EASY_STR2INT
// #define EASY_STR2UINT
/**TO HEX**/
// #define EASY_CHAR2HEX
// #define EASY_INT2HEX
/**BITS OPERATIONS**/
// #define EASY_READ_BIT_CHAR
// #define EASY_UP_BIT_CHAR
// #define EASY_DOWN_BIT_CHAR
// #define EASY_INVERSE_BIT_CHAR
// #define EASY_READ_BIT_INT
// #define EASY_UP_BIT_INT
// #define EASY_DOWN_BIT_INT
// #define EASY_INVERSE_BIT_INT
/**FAST KEYS DETECTION**/
// #define EASY_KEY_DOWN
// #define EASY_KEY_UP
// #define EASY_ANY_KEY
/**OTHERS**/
// #define EASY_INPUT
// #define EASY_NUMARRAY_CHAR
// #define EASY_NUMARRAY_INT
/**USEFUL VARIABLES**/
// #define NULL 0
// #define EXIT_SUCCESS 1
/**************************/
/** Functions prototypes **/
/**************************/
typedef enum {EMULATOR, G35, G75, G85, G85SD, G95, UNDEFINED} Model;
/**MODEL DETECTION**/
char isEmulator();
char isG35p75();
char isG75(); // BESOIN DE LA VALEUR!!!
char isG85();
char isG85SD();
char isG95();
char hasSD();
Model modelDetector();
/**STRING MANIUPLATION**/
unsigned char* toLower(unsigned char* str);
unsigned char* toUpper(unsigned char* str);
unsigned char* strMirror(unsigned char* str);
unsigned char* strRotate(unsigned char* str, char mov);
void printf(unsigned char x, unsigned char y, unsigned char* str, char mode);
void printn(unsigned char x, unsigned char y, int n, char mode);
/**TO STRING OPERATIONS**/
unsigned char* intToStr(unsigned char* c, int n);
unsigned char* uintToStr(unsigned char* c, unsigned int n);
unsigned char* charToStr(unsigned char* c, char n);
unsigned char* ucharToStr(unsigned char* c, unsigned char n);
unsigned char* floatToStr(unsigned char* c, float f, int pecision);
/**TO NUMBER**/
char strToChar(unsigned char* c);
unsigned char strToUchar(unsigned char* c);
int strToInt(unsigned char* c);
unsigned int strToUint(unsigned char* c);
/**TO HEX**/
char* charToHex(char* result, unsigned char hex);
char* intToHex(char* result, unsigned int hex);
/**BITS OPERATIONS**/
char readBit_char(char num, char index);
char inverseBit_char(char num, char index);
char upBit_char(char num, char index);
char downBit_char(char num, char index);
char readBit_int(int num, char index);
int inverseBit_int(int num, char index);
int upBit_int(int num, char index);
int downBit_int(int num, char index);
/**KEY DETECTION**/
unsigned char KeyDown( unsigned char code);
unsigned char KeyUp( unsigned char code);
unsigned char AnyKey();
/**OTHERS**/
char* input(char* c, int x, int y, int longueur, char nb);
int numArray_char(char* arr);
int numArray_int(char* arr);
/********************/
/** Key Codes List **/
/********************/
#define K_F1 0x69
#define K_F2 0x59
#define K_F3 0x49
#define K_F4 0x39
#define K_F5 0x29
#define K_F6 0x19
#define K_SHIFT 0x68
#define K_OPTN 0x58
#define K_VARS 0x48
#define K_MENU 0x38
#define K_LEFT 0x28
#define K_UP 0x18
#define K_ALPHA 0x67
#define K_SQR 0x57
#define K_EXPO 0x47
#define K_EXIT 0x37
#define K_DOWN 0x27
#define K_RIGHT 0x17
#define K_THETA 0x66
#define K_LOG 0x56
#define K_LN 0x46
#define K_SIN 0x36
#define K_COS 0x26
#define K_TAN 0x16
#define K_FRAC 0x65
#define K_FD 0x55
#define K_LPAR 0x45
#define K_RPAR 0x35
#define K_COMMA 0x25
#define K_STORE 0x15
#define K_7 0x64
#define K_8 0x54
#define K_9 0x44
#define K_DEL 0x34
#define K_4 0x63
#define K_5 0x53
#define K_6 0x43
#define K_MULT 0x33
#define K_DIV 0x23
#define K_1 0x62
#define K_2 0x52
#define K_3 0x42
#define K_PLUS 0x32
#define K_MINUS 0x22
#define K_0 0x61
#define K_DOT 0x51
#define K_EXP 0x41
#define K_NEG 0x31
#define K_EXE 0x21
#define K_AC 0x00
#endif //EASYCODE
/*****************************************************************/
/* */
/* CASIO fx-9860G SDK Library */
/* */
/* File name : [ProjectName].c */
/* */
/* Copyright (c) 2006 CASIO COMPUTER CO., LTD. */
/* */
/*****************************************************************/
extern "C" {
#include "fxlib.h"
#include "ECode.h"
#include "MonochromeLib.h"
#include "time.h"
}
#include "Matrices.h"
#include "CasGL.h"
#define LENGTH 30
int main() {
int i;
float z = 0;
Matrix4 view, projection;
Vector4 points[LENGTH] = {
// Face devant
Vector4(-1, -1, -1, 1),
Vector4( 1, -1, -1, 1),
Vector4(-1, -1, -1, 1),
Vector4(-1, 1, -1, 1),
Vector4( 1, -1, -1, 1),
Vector4( 1, 1, -1, 1),
Vector4( 1, 1, -1, 1),
Vector4(-1, 1, -1, 1),
// Face derrière
Vector4(-1, -1, 1, 1),
Vector4( 1, -1, 1, 1),
Vector4(-1, -1, 1, 1),
Vector4(-1, 1, 1, 1),
Vector4( 1, -1, 1, 1),
Vector4( 1, 1, 1, 1),
Vector4( 1, 1, 1, 1),
Vector4(-1, 1, 1, 1),
// Et on relie
Vector4(-1, 1, -1, 1),
Vector4(-1, 1, 1, 1),
Vector4( 1, 1, -1, 1),
Vector4( 1, 1, 1, 1),
Vector4(-1, -1, -1, 1),
Vector4(-1, -1, 1, 1),
Vector4( 1, -1, -1, 1),
Vector4( 1, -1, 1, 1),
// Et le repère
Vector4(0, 0, 0, 1),
Vector4(1, 0, 0, 1),
Vector4(0, 0, 0, 1),
Vector4(0, 1, 0, 1),
Vector4(0, 0, 0, 1),
Vector4(0, 0, 1, 1)
};
Vector4 buffer[LENGTH];
projection = GL_ProjectionMatrixFovRH(50 * DEG2RAD, 0.7, 0.01, 2000);
while(1){
ML_clear_vram();
view = GL_LookAtMatrixRH(
Vector3(sinf(z) * 15, cosf(z * 0.45) * 15, cosf(z) * 15),
Vector3(0, 0, 0),
Vector3(0, 1, 0)
);
for(i = 0; i < LENGTH; i++)
{
// Eye coordinates
buffer[i] = view * points[i];
buffer[i] = projection * buffer[i];
// NDC
buffer[i] /= buffer[i].w;
buffer[i].x += 64;
buffer[i].y += 32;
if(i%2 == 1)
ML_line(
(unsigned char) buffer[i-1].x, (unsigned char) buffer[i-1].y,
(unsigned char) buffer[i].x, (unsigned char) buffer[i].y,
ML_BLACK);
}
ML_display_vram();
setFps(3);
z -= 0.05;
}
return 1;
}
extern "C" {
//****************************************************************************
// AddIn_main (Sample program main function)
//
// param : isAppli : 1 = This application is launched by MAIN MENU.
// : 0 = This application is launched by a strip in eACT application.
//
// OptionNum : Strip number (0~3)
// (This parameter is only used when isAppli parameter is 0.)
//
// retval : 1 = No error / 0 = Error
//
//****************************************************************************
int AddIn_main(int isAppli, unsigned short OptionNum)
{
return main();
}
//****************************************************************************
//************** ****************
//************** Notice! ****************
//************** ****************
//************** Please do not change the following source. ****************
//************** ****************
//****************************************************************************
#pragma section _BR_Size
unsigned long BR_Size;
#pragma section
#pragma section _TOP
//****************************************************************************
// InitializeSystem
//
// param : isAppli : 1 = Application / 0 = eActivity
// OptionNum : Option Number (only eActivity)
//
// retval : 1 = No error / 0 = Error
//
//****************************************************************************
int InitializeSystem(int isAppli, unsigned short OptionNum)
{
return INIT_ADDIN_APPLICATION(isAppli, OptionNum);
}
#pragma section
}
///////////////////////////////////////////////////////////////////////////////
// Matrice.cpp
// ===========
// NxN Matrix Math classes
//
// The elements of the matrix are stored as column major order.
// | 0 2 | | 0 3 6 | | 0 4 8 12 |
// | 1 3 | | 1 4 7 | | 1 5 9 13 |
// | 2 5 8 | | 2 6 10 14 |
// | 3 7 11 15 |
//
// AUTHOR: Song Ho Ahn (song.ahn@gmail.com)
// CREATED: 2005-06-24
// UPDATED: 2014-09-21
//
// Copyright (C) 2005 Song Ho Ahn
///////////////////////////////////////////////////////////////////////////////
#include <math.h>
#include "Matrices.h"
///////////////////////////////////////////////////////////////////////////////
// return the determinant of 2x2 matrix
///////////////////////////////////////////////////////////////////////////////
float Matrix2::getDeterminant()
{
return m[0] * m[3] - m[1] * m[2];
}
///////////////////////////////////////////////////////////////////////////////
// inverse of 2x2 matrix
// If cannot find inverse, set identity matrix
///////////////////////////////////////////////////////////////////////////////
Matrix2& Matrix2::invert()
{
float determinant = getDeterminant();
if(fabs(determinant) <= EPSILON)
{
return identity();
}
float tmp = m[0]; // copy the first element
float invDeterminant = 1.0f / determinant;
m[0] = invDeterminant * m[3];
m[1] = -invDeterminant * m[1];
m[2] = -invDeterminant * m[2];
m[3] = invDeterminant * tmp;
return *this;
}
///////////////////////////////////////////////////////////////////////////////
// return determinant of 3x3 matrix
///////////////////////////////////////////////////////////////////////////////
float Matrix3::getDeterminant()
{
return m[0] * (m[4] * m[8] - m[5] * m[7]) -
m[1] * (m[3] * m[8] - m[5] * m[6]) +
m[2] * (m[3] * m[7] - m[4] * m[6]);
}
///////////////////////////////////////////////////////////////////////////////
// inverse 3x3 matrix
// If cannot find inverse, set identity matrix
///////////////////////////////////////////////////////////////////////////////
Matrix3& Matrix3::invert()
{
float determinant, invDeterminant;
float tmp[9];
tmp[0] = m[4] * m[8] - m[5] * m[7];
tmp[1] = m[2] * m[7] - m[1] * m[8];
tmp[2] = m[1] * m[5] - m[2] * m[4];
tmp[3] = m[5] * m[6] - m[3] * m[8];
tmp[4] = m[0] * m[8] - m[2] * m[6];
tmp[5] = m[2] * m[3] - m[0] * m[5];
tmp[6] = m[3] * m[7] - m[4] * m[6];
tmp[7] = m[1] * m[6] - m[0] * m[7];
tmp[8] = m[0] * m[4] - m[1] * m[3];
// check determinant if it is 0
determinant = m[0] * tmp[0] + m[1] * tmp[3] + m[2] * tmp[6];
if(fabs(determinant) <= EPSILON)
{
return identity(); // cannot inverse, make it idenety matrix
}
// divide by the determinant
invDeterminant = 1.0f / determinant;
m[0] = invDeterminant * tmp[0];
m[1] = invDeterminant * tmp[1];
m[2] = invDeterminant * tmp[2];
m[3] = invDeterminant * tmp[3];
m[4] = invDeterminant * tmp[4];
m[5] = invDeterminant * tmp[5];
m[6] = invDeterminant * tmp[6];
m[7] = invDeterminant * tmp[7];
m[8] = invDeterminant * tmp[8];
return *this;
}
///////////////////////////////////////////////////////////////////////////////
// inverse 4x4 matrix
///////////////////////////////////////////////////////////////////////////////
Matrix4& Matrix4::invert()
{
// If the 4th row is [0,0,0,1] then it is affine matrix and
// it has no projective transformation.
if(m[3] == 0 && m[7] == 0 && m[11] == 0 && m[15] == 1)
this->invertAffine();
else
{
this->invertGeneral();
/*@@ invertProjective() is not optimized (slower than generic one)
if(fabs(m[0]*m[5] - m[1]*m[4]) > EPSILON)
this->invertProjective(); // inverse using matrix partition
else
this->invertGeneral(); // generalized inverse
*/
}
return *this;
}
///////////////////////////////////////////////////////////////////////////////
// compute the inverse of 4x4 Euclidean transformation matrix
//
// Euclidean transformation is translation, rotation, and reflection.
// With Euclidean transform, only the position and orientation of the object
// will be changed. Euclidean transform does not change the shape of an object
// (no scaling). Length and angle are reserved.
//
// Use inverseAffine() if the matrix has scale and shear transformation.
//
// M = [ R | T ]
// [ --+-- ] (R denotes 3x3 rotation/reflection matrix)
// [ 0 | 1 ] (T denotes 1x3 translation matrix)
//
// y = M*x -> y = R*x + T -> x = R^-1*(y - T) -> x = R^T*y - R^T*T
// (R is orthogonal, R^-1 = R^T)
//
// [ R | T ]-1 [ R^T | -R^T * T ] (R denotes 3x3 rotation matrix)
// [ --+-- ] = [ ----+--------- ] (T denotes 1x3 translation)
// [ 0 | 1 ] [ 0 | 1 ] (R^T denotes R-transpose)
///////////////////////////////////////////////////////////////////////////////
Matrix4& Matrix4::invertEuclidean()
{
// transpose 3x3 rotation matrix part
// | R^T | 0 |
// | ----+-- |
// | 0 | 1 |
float tmp;
tmp = m[1]; m[1] = m[4]; m[4] = tmp;
tmp = m[2]; m[2] = m[8]; m[8] = tmp;
tmp = m[6]; m[6] = m[9]; m[9] = tmp;
// compute translation part -R^T * T
// | 0 | -R^T x |
// | --+------- |
// | 0 | 0 |
float x = m[12];
float y = m[13];
float z = m[14];
m[12] = -(m[0] * x + m[4] * y + m[8] * z);
m[13] = -(m[1] * x + m[5] * y + m[9] * z);
m[14] = -(m[2] * x + m[6] * y + m[10]* z);
// last row should be unchanged (0,0,0,1)
return *this;
}
///////////////////////////////////////////////////////////////////////////////
// compute the inverse of a 4x4 affine transformation matrix
//
// Affine transformations are generalizations of Euclidean transformations.
// Affine transformation includes translation, rotation, reflection, scaling,
// and shearing. Length and angle are NOT preserved.
// M = [ R | T ]
// [ --+-- ] (R denotes 3x3 rotation/scale/shear matrix)
// [ 0 | 1 ] (T denotes 1x3 translation matrix)
//
// y = M*x -> y = R*x + T -> x = R^-1*(y - T) -> x = R^-1*y - R^-1*T
//
// [ R | T ]-1 [ R^-1 | -R^-1 * T ]
// [ --+-- ] = [ -----+---------- ]
// [ 0 | 1 ] [ 0 + 1 ]
///////////////////////////////////////////////////////////////////////////////
Matrix4& Matrix4::invertAffine()
{
// R^-1
Matrix3 r(m[0],m[1],m[2], m[4],m[5],m[6], m[8],m[9],m[10]);
r.invert();
m[0] = r[0]; m[1] = r[1]; m[2] = r[2];
m[4] = r[3]; m[5] = r[4]; m[6] = r[5];
m[8] = r[6]; m[9] = r[7]; m[10]= r[8];
// -R^-1 * T
float x = m[12];
float y = m[13];
float z = m[14];
m[12] = -(r[0] * x + r[3] * y + r[6] * z);
m[13] = -(r[1] * x + r[4] * y + r[7] * z);
m[14] = -(r[2] * x + r[5] * y + r[8] * z);
// last row should be unchanged (0,0,0,1)
//m[3] = m[7] = m[11] = 0.0f;
//m[15] = 1.0f;
return * this;
}
///////////////////////////////////////////////////////////////////////////////
// inverse matrix using matrix partitioning (blockwise inverse)
// It devides a 4x4 matrix into 4 of 2x2 matrices. It works in case of where
// det(A) != 0. If not, use the generic inverse method
// inverse formula.
// M = [ A | B ] A, B, C, D are 2x2 matrix blocks
// [ --+-- ] det(M) = |A| * |D - ((C * A^-1) * B)|
// [ C | D ]
//
// M^-1 = [ A' | B' ] A' = A^-1 - (A^-1 * B) * C'
// [ ---+--- ] B' = (A^-1 * B) * -D'
// [ C' | D' ] C' = -D' * (C * A^-1)
// D' = (D - ((C * A^-1) * B))^-1
//
// NOTE: I wrap with () if it it used more than once.
// The matrix is invertable even if det(A)=0, so must check det(A) before
// calling this function, and use invertGeneric() instead.
///////////////////////////////////////////////////////////////////////////////
Matrix4& Matrix4::invertProjective()
{
// partition
Matrix2 a(m[0], m[1], m[4], m[5]);
Matrix2 b(m[8], m[9], m[12], m[13]);
Matrix2 c(m[2], m[3], m[6], m[7]);
Matrix2 d(m[10], m[11], m[14], m[15]);
// pre-compute repeated parts
a.invert(); // A^-1
Matrix2 ab = a * b; // A^-1 * B
Matrix2 ca = c * a; // C * A^-1
Matrix2 cab = ca * b; // C * A^-1 * B
Matrix2 dcab = d - cab; // D - C * A^-1 * B
// check determinant if |D - C * A^-1 * B| = 0
//NOTE: this function assumes det(A) is already checked. if |A|=0 then,
// cannot use this function.
float determinant = dcab[0] * dcab[3] - dcab[1] * dcab[2];
if(fabs(determinant) <= EPSILON)
{
return identity();
}
// compute D' and -D'
Matrix2 d1 = dcab; // (D - C * A^-1 * B)
d1.invert(); // (D - C * A^-1 * B)^-1
Matrix2 d2 = -d1; // -(D - C * A^-1 * B)^-1
// compute C'
Matrix2 c1 = d2 * ca; // -D' * (C * A^-1)
// compute B'
Matrix2 b1 = ab * d2; // (A^-1 * B) * -D'
// compute A'
Matrix2 a1 = a - (ab * c1); // A^-1 - (A^-1 * B) * C'
// assemble inverse matrix
m[0] = a1[0]; m[4] = a1[2]; /*|*/ m[8] = b1[0]; m[12]= b1[2];
m[1] = a1[1]; m[5] = a1[3]; /*|*/ m[9] = b1[1]; m[13]= b1[3];
/*-----------------------------+-----------------------------*/
m[2] = c1[0]; m[6] = c1[2]; /*|*/ m[10]= d1[0]; m[14]= d1[2];
m[3] = c1[1]; m[7] = c1[3]; /*|*/ m[11]= d1[1]; m[15]= d1[3];
return *this;
}
///////////////////////////////////////////////////////////////////////////////
// compute the inverse of a general 4x4 matrix using Cramer's Rule
// If cannot find inverse, return indentity matrix
// M^-1 = adj(M) / det(M)
///////////////////////////////////////////////////////////////////////////////
Matrix4& Matrix4::invertGeneral()
{
// get cofactors of minor matrices
float cofactor0 = getCofactor(m[5],m[6],m[7], m[9],m[10],m[11], m[13],m[14],m[15]);
float cofactor1 = getCofactor(m[4],m[6],m[7], m[8],m[10],m[11], m[12],m[14],m[15]);
float cofactor2 = getCofactor(m[4],m[5],m[7], m[8],m[9], m[11], m[12],m[13],m[15]);
float cofactor3 = getCofactor(m[4],m[5],m[6], m[8],m[9], m[10], m[12],m[13],m[14]);
// get determinant
float determinant = m[0] * cofactor0 - m[1] * cofactor1 + m[2] * cofactor2 - m[3] * cofactor3;
if(fabs(determinant) <= EPSILON)
{
return identity();
}
// get rest of cofactors for adj(M)
float cofactor4 = getCofactor(m[1],m[2],m[3], m[9],m[10],m[11], m[13],m[14],m[15]);
float cofactor5 = getCofactor(m[0],m[2],m[3], m[8],m[10],m[11], m[12],m[14],m[15]);
float cofactor6 = getCofactor(m[0],m[1],m[3], m[8],m[9], m[11], m[12],m[13],m[15]);
float cofactor7 = getCofactor(m[0],m[1],m[2], m[8],m[9], m[10], m[12],m[13],m[14]);
float cofactor8 = getCofactor(m[1],m[2],m[3], m[5],m[6], m[7], m[13],m[14],m[15]);
float cofactor9 = getCofactor(m[0],m[2],m[3], m[4],m[6], m[7], m[12],m[14],m[15]);
float cofactor10= getCofactor(m[0],m[1],m[3], m[4],m[5], m[7], m[12],m[13],m[15]);
float cofactor11= getCofactor(m[0],m[1],m[2], m[4],m[5], m[6], m[12],m[13],m[14]);
float cofactor12= getCofactor(m[1],m[2],m[3], m[5],m[6], m[7], m[9], m[10],m[11]);
float cofactor13= getCofactor(m[0],m[2],m[3], m[4],m[6], m[7], m[8], m[10],m[11]);
float cofactor14= getCofactor(m[0],m[1],m[3], m[4],m[5], m[7], m[8], m[9], m[11]);
float cofactor15= getCofactor(m[0],m[1],m[2], m[4],m[5], m[6], m[8], m[9], m[10]);
// build inverse matrix = adj(M) / det(M)
// adjugate of M is the transpose of the cofactor matrix of M
float invDeterminant = 1.0f / determinant;
m[0] = invDeterminant * cofactor0;
m[1] = -invDeterminant * cofactor4;
m[2] = invDeterminant * cofactor8;
m[3] = -invDeterminant * cofactor12;
m[4] = -invDeterminant * cofactor1;
m[5] = invDeterminant * cofactor5;
m[6] = -invDeterminant * cofactor9;
m[7] = invDeterminant * cofactor13;
m[8] = invDeterminant * cofactor2;
m[9] = -invDeterminant * cofactor6;
m[10]= invDeterminant * cofactor10;
m[11]= -invDeterminant * cofactor14;
m[12]= -invDeterminant * cofactor3;
m[13]= invDeterminant * cofactor7;
m[14]= -invDeterminant * cofactor11;
m[15]= invDeterminant * cofactor15;
return *this;
}
///////////////////////////////////////////////////////////////////////////////
// return determinant of 4x4 matrix
///////////////////////////////////////////////////////////////////////////////
float Matrix4::getDeterminant()
{
return m[0] * getCofactor(m[5],m[6],m[7], m[9],m[10],m[11], m[13],m[14],m[15]) -
m[1] * getCofactor(m[4],m[6],m[7], m[8],m[10],m[11], m[12],m[14],m[15]) +
m[2] * getCofactor(m[4],m[5],m[7], m[8],m[9], m[11], m[12],m[13],m[15]) -
m[3] * getCofactor(m[4],m[5],m[6], m[8],m[9], m[10], m[12],m[13],m[14]);
}
///////////////////////////////////////////////////////////////////////////////
// compute cofactor of 3x3 minor matrix without sign
// input params are 9 elements of the minor matrix
// NOTE: The caller must know its sign.
///////////////////////////////////////////////////////////////////////////////
float Matrix4::getCofactor(float m0, float m1, float m2,
float m3, float m4, float m5,
float m6, float m7, float m8)
{
return m0 * (m4 * m8 - m5 * m7) -
m1 * (m3 * m8 - m5 * m6) +
m2 * (m3 * m7 - m4 * m6);
}
///////////////////////////////////////////////////////////////////////////////
// translate this matrix by (x, y, z)
///////////////////////////////////////////////////////////////////////////////
Matrix4& Matrix4::translate(const Vector3& v)
{
return translate(v.x, v.y, v.z);
}
Matrix4& Matrix4::translate(float x, float y, float z)
{
m[0] += m[3] * x; m[4] += m[7] * x; m[8] += m[11]* x; m[12]+= m[15]* x;
m[1] += m[3] * y; m[5] += m[7] * y; m[9] += m[11]* y; m[13]+= m[15]* y;
m[2] += m[3] * z; m[6] += m[7] * z; m[10]+= m[11]* z; m[14]+= m[15]* z;
return *this;
}
///////////////////////////////////////////////////////////////////////////////
// uniform scale
///////////////////////////////////////////////////////////////////////////////
Matrix4& Matrix4::scale(float s)
{
return scale(s, s, s);
}
Matrix4& Matrix4::scale(float x, float y, float z)
{
m[0] *= x; m[4] *= x; m[8] *= x; m[12] *= x;
m[1] *= y; m[5] *= y; m[9] *= y; m[13] *= y;
m[2] *= z; m[6] *= z; m[10]*= z; m[14] *= z;
return *this;
}
///////////////////////////////////////////////////////////////////////////////
// build a rotation matrix with given angle(degree) and rotation axis, then
// multiply it with this object
///////////////////////////////////////////////////////////////////////////////
Matrix4& Matrix4::rotate(float angle, const Vector3& axis)
{
return rotate(angle, axis.x, axis.y, axis.z);
}
Matrix4& Matrix4::rotate(float angle, float x, float y, float z)
{
float c = cosf(angle * DEG2RAD); // cosine
float s = sinf(angle * DEG2RAD); // sine
float c1 = 1.0f - c; // 1 - c
float m0 = m[0], m4 = m[4], m8 = m[8], m12= m[12],
m1 = m[1], m5 = m[5], m9 = m[9], m13= m[13],
m2 = m[2], m6 = m[6], m10= m[10], m14= m[14];
// build rotation matrix
float r0 = x * x * c1 + c;
float r1 = x * y * c1 + z * s;
float r2 = x * z * c1 - y * s;
float r4 = x * y * c1 - z * s;
float r5 = y * y * c1 + c;
float r6 = y * z * c1 + x * s;
float r8 = x * z * c1 + y * s;
float r9 = y * z * c1 - x * s;
float r10= z * z * c1 + c;
// multiply rotation matrix
m[0] = r0 * m0 + r4 * m1 + r8 * m2;
m[1] = r1 * m0 + r5 * m1 + r9 * m2;
m[2] = r2 * m0 + r6 * m1 + r10* m2;
m[4] = r0 * m4 + r4 * m5 + r8 * m6;
m[5] = r1 * m4 + r5 * m5 + r9 * m6;
m[6] = r2 * m4 + r6 * m5 + r10* m6;
m[8] = r0 * m8 + r4 * m9 + r8 * m10;
m[9] = r1 * m8 + r5 * m9 + r9 * m10;
m[10]= r2 * m8 + r6 * m9 + r10* m10;
m[12]= r0 * m12+ r4 * m13+ r8 * m14;
m[13]= r1 * m12+ r5 * m13+ r9 * m14;
m[14]= r2 * m12+ r6 * m13+ r10* m14;
return *this;
}
Matrix4& Matrix4::rotateX(float angle)
{
float c = cosf(angle * DEG2RAD);
float s = sinf(angle * DEG2RAD);
float m1 = m[1], m2 = m[2],
m5 = m[5], m6 = m[6],
m9 = m[9], m10= m[10],
m13= m[13], m14= m[14];
m[1] = m1 * c + m2 *-s;
m[2] = m1 * s + m2 * c;
m[5] = m5 * c + m6 *-s;
m[6] = m5 * s + m6 * c;
m[9] = m9 * c + m10*-s;
m[10]= m9 * s + m10* c;
m[13]= m13* c + m14*-s;
m[14]= m13* s + m14* c;
return *this;
}
Matrix4& Matrix4::rotateY(float angle)
{
float c = cosf(angle * DEG2RAD);
float s = sinf(angle * DEG2RAD);
float m0 = m[0], m2 = m[2],
m4 = m[4], m6 = m[6],
m8 = m[8], m10= m[10],
m12= m[12], m14= m[14];
m[0] = m0 * c + m2 * s;
m[2] = m0 *-s + m2 * c;
m[4] = m4 * c + m6 * s;
m[6] = m4 *-s + m6 * c;
m[8] = m8 * c + m10* s;
m[10]= m8 *-s + m10* c;
m[12]= m12* c + m14* s;
m[14]= m12*-s + m14* c;
return *this;
}
Matrix4& Matrix4::rotateZ(float angle)
{
float c = cosf(angle * DEG2RAD);
float s = sinf(angle * DEG2RAD);
float m0 = m[0], m1 = m[1],
m4 = m[4], m5 = m[5],
m8 = m[8], m9 = m[9],
m12= m[12], m13= m[13];
m[0] = m0 * c + m1 *-s;
m[1] = m0 * s + m1 * c;
m[4] = m4 * c + m5 *-s;
m[5] = m4 * s + m5 * c;
m[8] = m8 * c + m9 *-s;
m[9] = m8 * s + m9 * c;
m[12]= m12* c + m13*-s;
m[13]= m12* s + m13* c;
return *this;
}
///////////////////////////////////////////////////////////////////////////////
// Matrice.h
// =========
// NxN Matrix Math classes
//
// The elements of the matrix are stored as column major order.
// | 0 2 | | 0 3 6 | | 0 4 8 12 |
// | 1 3 | | 1 4 7 | | 1 5 9 13 |
// | 2 5 8 | | 2 6 10 14 |
// | 3 7 11 15 |
//
// AUTHOR: Song Ho Ahn (song.ahn@gmail.com)
// CREATED: 2005-06-24
// UPDATED: 2013-09-30
//
// Copyright (C) 2005 Song Ho Ahn
///////////////////////////////////////////////////////////////////////////////
#pragma once
const float DEG2RAD = 3.141593f / 180;
const float EPSILON = 0.00001f;
#include "Vectors.h"
///////////////////////////////////////////////////////////////////////////
// 2x2 matrix
///////////////////////////////////////////////////////////////////////////
class Matrix2
{
public:
// constructors
Matrix2(); // init with identity
Matrix2(const float src[4]);
Matrix2(float m0, float m1, float m2, float m3);
void set(const float src[4]);
void set(float m0, float m1, float m2, float m3);
void setRow(int index, const float row[2]);
void setRow(int index, const Vector2& v);
void setColumn(int index, const float col[2]);
void setColumn(int index, const Vector2& v);
const float* get() const;
float getDeterminant();
Matrix2& identity();
Matrix2& invert();
// operators
Matrix2 operator+(const Matrix2& rhs) const; // add rhs
Matrix2 operator-(const Matrix2& rhs) const; // subtract rhs
Matrix2& operator+=(const Matrix2& rhs); // add rhs and update this object
Matrix2& operator-=(const Matrix2& rhs); // subtract rhs and update this object
Vector2 operator*(const Vector2& rhs) const; // multiplication: v' = M * v
Matrix2 operator*(const Matrix2& rhs) const; // multiplication: M3 = M1 * M2
Matrix2& operator*=(const Matrix2& rhs); // multiplication: M1' = M1 * M2
bool operator==(const Matrix2& rhs) const; // exact compare, no epsilon
bool operator!=(const Matrix2& rhs) const; // exact compare, no epsilon
float operator[](int index) const; // subscript operator v[0], v[1]
float& operator[](int index); // subscript operator v[0], v[1]
friend Matrix2 operator-(const Matrix2& m); // unary operator (-)
friend Matrix2 operator*(float scalar, const Matrix2& m); // pre-multiplication
friend Vector2 operator*(const Vector2& vec, const Matrix2& m); // pre-multiplication
protected:
private:
float m[4];
};
///////////////////////////////////////////////////////////////////////////
// 3x3 matrix
///////////////////////////////////////////////////////////////////////////
class Matrix3
{
public:
// constructors
Matrix3(); // init with identity
Matrix3(const float src[9]);
Matrix3(float m0, float m1, float m2, // 1st column
float m3, float m4, float m5, // 2nd column
float m6, float m7, float m8); // 3rd column
void set(const float src[9]);
void set(float m0, float m1, float m2, // 1st column
float m3, float m4, float m5, // 2nd column
float m6, float m7, float m8); // 3rd column
void setRow(int index, const float row[3]);
void setRow(int index, const Vector3& v);
void setColumn(int index, const float col[3]);
void setColumn(int index, const Vector3& v);
const float* get() const;
float getDeterminant();
Matrix3& identity();
Matrix3& invert();
// operators
Matrix3 operator+(const Matrix3& rhs) const; // add rhs
Matrix3 operator-(const Matrix3& rhs) const; // subtract rhs
Matrix3& operator+=(const Matrix3& rhs); // add rhs and update this object
Matrix3& operator-=(const Matrix3& rhs); // subtract rhs and update this object
Vector3 operator*(const Vector3& rhs) const; // multiplication: v' = M * v
Matrix3 operator*(const Matrix3& rhs) const; // multiplication: M3 = M1 * M2
Matrix3& operator*=(const Matrix3& rhs); // multiplication: M1' = M1 * M2
bool operator==(const Matrix3& rhs) const; // exact compare, no epsilon
bool operator!=(const Matrix3& rhs) const; // exact compare, no epsilon
float operator[](int index) const; // subscript operator v[0], v[1]
float& operator[](int index); // subscript operator v[0], v[1]
friend Matrix3 operator-(const Matrix3& m); // unary operator (-)
friend Matrix3 operator*(float scalar, const Matrix3& m); // pre-multiplication
friend Vector3 operator*(const Vector3& vec, const Matrix3& m); // pre-multiplication
protected:
private:
float m[9];
};
///////////////////////////////////////////////////////////////////////////
// 4x4 matrix
///////////////////////////////////////////////////////////////////////////
class Matrix4
{
public:
// constructors
Matrix4(); // init with identity
Matrix4(const float src[16]);
Matrix4(float m00, float m01, float m02, float m03, // 1st column
float m04, float m05, float m06, float m07, // 2nd column
float m08, float m09, float m10, float m11, // 3rd column
float m12, float m13, float m14, float m15);// 4th column
void set(const float src[16]);
void set(float m00, float m01, float m02, float m03, // 1st column
float m04, float m05, float m06, float m07, // 2nd column
float m08, float m09, float m10, float m11, // 3rd column
float m12, float m13, float m14, float m15);// 4th column
void setRow(int index, const float row[4]);
void setRow(int index, const Vector4& v);
void setRow(int index, const Vector3& v);
void setColumn(int index, const float col[4]);
void setColumn(int index, const Vector4& v);
void setColumn(int index, const Vector3& v);
const float* get() const;
float getDeterminant();
Matrix4& identity();
Matrix4& invert(); // check best inverse method before inverse
Matrix4& invertEuclidean(); // inverse of Euclidean transform matrix
Matrix4& invertAffine(); // inverse of affine transform matrix
Matrix4& invertProjective(); // inverse of projective matrix using partitioning
Matrix4& invertGeneral(); // inverse of generic matrix
// transform matrix
Matrix4& translate(float x, float y, float z); // translation by (x,y,z)
Matrix4& translate(const Vector3& v); //
Matrix4& rotate(float angle, const Vector3& axis); // rotate angle(degree) along the given axix
Matrix4& rotate(float angle, float x, float y, float z);
Matrix4& rotateX(float angle); // rotate on X-axis with degree
Matrix4& rotateY(float angle); // rotate on Y-axis with degree
Matrix4& rotateZ(float angle); // rotate on Z-axis with degree
Matrix4& scale(float scale); // uniform scale
Matrix4& scale(float sx, float sy, float sz); // scale by (sx, sy, sz) on each axis
// operators
Matrix4 operator+(const Matrix4& rhs) const; // add rhs
Matrix4 operator-(const Matrix4& rhs) const; // subtract rhs
Matrix4& operator+=(const Matrix4& rhs); // add rhs and update this object
Matrix4& operator-=(const Matrix4& rhs); // subtract rhs and update this object
Vector4 operator*(const Vector4& rhs) const; // multiplication: v' = M * v
Vector3 operator*(const Vector3& rhs) const; // multiplication: v' = M * v
Matrix4 operator*(const Matrix4& rhs) const; // multiplication: M3 = M1 * M2
Matrix4& operator*=(const Matrix4& rhs); // multiplication: M1' = M1 * M2
bool operator==(const Matrix4& rhs) const; // exact compare, no epsilon
bool operator!=(const Matrix4& rhs) const; // exact compare, no epsilon
float operator[](int index) const; // subscript operator v[0], v[1]
float& operator[](int index); // subscript operator v[0], v[1]
friend Matrix4 operator-(const Matrix4& m); // unary operator (-)
friend Matrix4 operator*(float scalar, const Matrix4& m); // pre-multiplication
friend Vector3 operator*(const Vector3& vec, const Matrix4& m); // pre-multiplication
friend Vector4 operator*(const Vector4& vec, const Matrix4& m); // pre-multiplication
protected:
private:
float getCofactor(float m0, float m1, float m2,
float m3, float m4, float m5,
float m6, float m7, float m8);
float m[16];
};
///////////////////////////////////////////////////////////////////////////
// inline functions for Matrix2
///////////////////////////////////////////////////////////////////////////
inline Matrix2::Matrix2()
{
// initially identity matrix
identity();
}
inline Matrix2::Matrix2(const float src[4])
{
set(src);
}
inline Matrix2::Matrix2(float m0, float m1, float m2, float m3)
{
set(m0, m1, m2, m3);
}
inline void Matrix2::set(const float src[4])
{
m[0] = src[0]; m[1] = src[1]; m[2] = src[2]; m[3] = src[3];
}
inline void Matrix2::set(float m0, float m1, float m2, float m3)
{
m[0]= m0; m[1] = m1; m[2] = m2; m[3]= m3;
}
inline void Matrix2::setRow(int index, const float row[2])
{
m[index] = row[0]; m[index + 2] = row[1];
}
inline void Matrix2::setRow(int index, const Vector2& v)
{
m[index] = v.x; m[index + 2] = v.y;
}
inline void Matrix2::setColumn(int index, const float col[2])
{
m[index*2] = col[0]; m[index*2 + 1] = col[1];
}
inline void Matrix2::setColumn(int index, const Vector2& v)
{
m[index*2] = v.x; m[index*2 + 1] = v.y;
}
inline const float* Matrix2::get() const
{
return m;
}
inline Matrix2& Matrix2::identity()
{
m[0] = m[3] = 1.0f;
m[1] = m[2] = 0.0f;
return *this;
}
inline Matrix2 Matrix2::operator+(const Matrix2& rhs) const
{
return Matrix2(m[0]+rhs[0], m[1]+rhs[1], m[2]+rhs[2], m[3]+rhs[3]);
}
inline Matrix2 Matrix2::operator-(const Matrix2& rhs) const
{
return Matrix2(m[0]-rhs[0], m[1]-rhs[1], m[2]-rhs[2], m[3]-rhs[3]);
}
inline Matrix2& Matrix2::operator+=(const Matrix2& rhs)
{
m[0] += rhs[0]; m[1] += rhs[1]; m[2] += rhs[2]; m[3] += rhs[3];
return *this;
}
inline Matrix2& Matrix2::operator-=(const Matrix2& rhs)
{
m[0] -= rhs[0]; m[1] -= rhs[1]; m[2] -= rhs[2]; m[3] -= rhs[3];
return *this;
}
inline Vector2 Matrix2::operator*(const Vector2& rhs) const
{
return Vector2(m[0]*rhs.x + m[2]*rhs.y, m[1]*rhs.x + m[3]*rhs.y);
}
inline Matrix2 Matrix2::operator*(const Matrix2& rhs) const
{
return Matrix2(m[0]*rhs[0] + m[2]*rhs[1], m[1]*rhs[0] + m[3]*rhs[1],
m[0]*rhs[2] + m[2]*rhs[3], m[1]*rhs[2] + m[3]*rhs[3]);
}
inline Matrix2& Matrix2::operator*=(const Matrix2& rhs)
{
*this = *this * rhs;
return *this;
}
inline bool Matrix2::operator==(const Matrix2& rhs) const
{
return (m[0] == rhs[0]) && (m[1] == rhs[1]) && (m[2] == rhs[2]) && (m[3] == rhs[3]);
}
inline bool Matrix2::operator!=(const Matrix2& rhs) const
{
return (m[0] != rhs[0]) || (m[1] != rhs[1]) || (m[2] != rhs[2]) || (m[3] != rhs[3]);
}
inline float Matrix2::operator[](int index) const
{
return m[index];
}
inline float& Matrix2::operator[](int index)
{
return m[index];
}
inline Matrix2 operator-(const Matrix2& rhs)
{
return Matrix2(-rhs[0], -rhs[1], -rhs[2], -rhs[3]);
}
inline Matrix2 operator*(float s, const Matrix2& rhs)
{
return Matrix2(s*rhs[0], s*rhs[1], s*rhs[2], s*rhs[3]);
}
inline Vector2 operator*(const Vector2& v, const Matrix2& rhs)
{
return Vector2(v.x*rhs[0] + v.y*rhs[1], v.x*rhs[2] + v.y*rhs[3]);
}
// END OF MATRIX2 INLINE //////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// inline functions for Matrix3
///////////////////////////////////////////////////////////////////////////
inline Matrix3::Matrix3()
{
// initially identity matrix
identity();
}
inline Matrix3::Matrix3(const float src[9])
{
set(src);
}
inline Matrix3::Matrix3(float m0, float m1, float m2,
float m3, float m4, float m5,
float m6, float m7, float m8)
{
set(m0, m1, m2, m3, m4, m5, m6, m7, m8);
}
inline void Matrix3::set(const float src[9])
{
m[0] = src[0]; m[1] = src[1]; m[2] = src[2];
m[3] = src[3]; m[4] = src[4]; m[5] = src[5];
m[6] = src[6]; m[7] = src[7]; m[8] = src[8];
}
inline void Matrix3::set(float m0, float m1, float m2,
float m3, float m4, float m5,
float m6, float m7, float m8)
{
m[0] = m0; m[1] = m1; m[2] = m2;
m[3] = m3; m[4] = m4; m[5] = m5;
m[6] = m6; m[7] = m7; m[8] = m8;
}
inline void Matrix3::setRow(int index, const float row[3])
{
m[index] = row[0]; m[index + 3] = row[1]; m[index + 6] = row[2];
}
inline void Matrix3::setRow(int index, const Vector3& v)
{
m[index] = v.x; m[index + 3] = v.y; m[index + 6] = v.z;
}
inline void Matrix3::setColumn(int index, const float col[3])
{
m[index*3] = col[0]; m[index*3 + 1] = col[1]; m[index*3 + 2] = col[2];
}
inline void Matrix3::setColumn(int index, const Vector3& v)
{
m[index*3] = v.x; m[index*3 + 1] = v.y; m[index*3 + 2] = v.z;
}
inline const float* Matrix3::get() const
{
return m;
}
inline Matrix3& Matrix3::identity()
{
m[0] = m[4] = m[8] = 1.0f;
m[1] = m[2] = m[3] = m[5] = m[6] = m[7] = 0.0f;
return *this;
}
inline Matrix3 Matrix3::operator+(const Matrix3& rhs) const
{
return Matrix3(m[0]+rhs[0], m[1]+rhs[1], m[2]+rhs[2],
m[3]+rhs[3], m[4]+rhs[4], m[5]+rhs[5],
m[6]+rhs[6], m[7]+rhs[7], m[8]+rhs[8]);
}
inline Matrix3 Matrix3::operator-(const Matrix3& rhs) const
{
return Matrix3(m[0]-rhs[0], m[1]-rhs[1], m[2]-rhs[2],
m[3]-rhs[3], m[4]-rhs[4], m[5]-rhs[5],
m[6]-rhs[6], m[7]-rhs[7], m[8]-rhs[8]);
}
inline Matrix3& Matrix3::operator+=(const Matrix3& rhs)
{
m[0] += rhs[0]; m[1] += rhs[1]; m[2] += rhs[2];
m[3] += rhs[3]; m[4] += rhs[4]; m[5] += rhs[5];
m[6] += rhs[6]; m[7] += rhs[7]; m[8] += rhs[8];
return *this;
}
inline Matrix3& Matrix3::operator-=(const Matrix3& rhs)
{
m[0] -= rhs[0]; m[1] -= rhs[1]; m[2] -= rhs[2];
m[3] -= rhs[3]; m[4] -= rhs[4]; m[5] -= rhs[5];
m[6] -= rhs[6]; m[7] -= rhs[7]; m[8] -= rhs[8];
return *this;
}
inline Vector3 Matrix3::operator*(const Vector3& rhs) const
{
return Vector3(m[0]*rhs.x + m[3]*rhs.y + m[6]*rhs.z,
m[1]*rhs.x + m[4]*rhs.y + m[7]*rhs.z,
m[2]*rhs.x + m[5]*rhs.y + m[8]*rhs.z);
}
inline Matrix3 Matrix3::operator*(const Matrix3& rhs) const
{
return Matrix3(m[0]*rhs[0] + m[3]*rhs[1] + m[6]*rhs[2], m[1]*rhs[0] + m[4]*rhs[1] + m[7]*rhs[2], m[2]*rhs[0] + m[5]*rhs[1] + m[8]*rhs[2],
m[0]*rhs[3] + m[3]*rhs[4] + m[6]*rhs[5], m[1]*rhs[3] + m[4]*rhs[4] + m[7]*rhs[5], m[2]*rhs[3] + m[5]*rhs[4] + m[8]*rhs[5],
m[0]*rhs[6] + m[3]*rhs[7] + m[6]*rhs[8], m[1]*rhs[6] + m[4]*rhs[7] + m[7]*rhs[8], m[2]*rhs[6] + m[5]*rhs[7] + m[8]*rhs[8]);
}
inline Matrix3& Matrix3::operator*=(const Matrix3& rhs)
{
*this = *this * rhs;
return *this;
}
inline bool Matrix3::operator==(const Matrix3& rhs) const
{
return (m[0] == rhs[0]) && (m[1] == rhs[1]) && (m[2] == rhs[2]) &&
(m[3] == rhs[3]) && (m[4] == rhs[4]) && (m[5] == rhs[5]) &&
(m[6] == rhs[6]) && (m[7] == rhs[7]) && (m[8] == rhs[8]);
}
inline bool Matrix3::operator!=(const Matrix3& rhs) const
{
return (m[0] != rhs[0]) || (m[1] != rhs[1]) || (m[2] != rhs[2]) ||
(m[3] != rhs[3]) || (m[4] != rhs[4]) || (m[5] != rhs[5]) ||
(m[6] != rhs[6]) || (m[7] != rhs[7]) || (m[8] != rhs[8]);
}
inline float Matrix3::operator[](int index) const
{
return m[index];
}
inline float& Matrix3::operator[](int index)
{
return m[index];
}
inline Matrix3 operator-(const Matrix3& rhs)
{
return Matrix3(-rhs[0], -rhs[1], -rhs[2], -rhs[3], -rhs[4], -rhs[5], -rhs[6], -rhs[7], -rhs[8]);
}
inline Matrix3 operator*(float s, const Matrix3& rhs)
{
return Matrix3(s*rhs[0], s*rhs[1], s*rhs[2], s*rhs[3], s*rhs[4], s*rhs[5], s*rhs[6], s*rhs[7], s*rhs[8]);
}
inline Vector3 operator*(const Vector3& v, const Matrix3& m)
{
return Vector3(v.x*m[0] + v.y*m[1] + v.z*m[2], v.x*m[3] + v.y*m[4] + v.z*m[5], v.x*m[6] + v.y*m[7] + v.z*m[8]);
}
// END OF MATRIX3 INLINE //////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// inline functions for Matrix4
///////////////////////////////////////////////////////////////////////////
inline Matrix4::Matrix4()
{
// initially identity matrix
identity();
}
inline Matrix4::Matrix4(const float src[16])
{
set(src);
}
inline Matrix4::Matrix4(float m00, float m01, float m02, float m03,
float m04, float m05, float m06, float m07,
float m08, float m09, float m10, float m11,
float m12, float m13, float m14, float m15)
{
set(m00, m01, m02, m03, m04, m05, m06, m07, m08, m09, m10, m11, m12, m13, m14, m15);
}
inline void Matrix4::set(const float src[16])
{
m[0] = src[0]; m[1] = src[1]; m[2] = src[2]; m[3] = src[3];
m[4] = src[4]; m[5] = src[5]; m[6] = src[6]; m[7] = src[7];
m[8] = src[8]; m[9] = src[9]; m[10]= src[10]; m[11]= src[11];
m[12]= src[12]; m[13]= src[13]; m[14]= src[14]; m[15]= src[15];
}
inline void Matrix4::set(float m00, float m01, float m02, float m03,
float m04, float m05, float m06, float m07,
float m08, float m09, float m10, float m11,
float m12, float m13, float m14, float m15)
{
m[0] = m00; m[1] = m01; m[2] = m02; m[3] = m03;
m[4] = m04; m[5] = m05; m[6] = m06; m[7] = m07;
m[8] = m08; m[9] = m09; m[10]= m10; m[11]= m11;
m[12]= m12; m[13]= m13; m[14]= m14; m[15]= m15;
}
inline void Matrix4::setRow(int index, const float row[4])
{
m[index] = row[0]; m[index + 4] = row[1]; m[index + 8] = row[2]; m[index + 12] = row[3];
}
inline void Matrix4::setRow(int index, const Vector4& v)
{
m[index] = v.x; m[index + 4] = v.y; m[index + 8] = v.z; m[index + 12] = v.w;
}
inline void Matrix4::setRow(int index, const Vector3& v)
{
m[index] = v.x; m[index + 4] = v.y; m[index + 8] = v.z;
}
inline void Matrix4::setColumn(int index, const float col[4])
{
m[index*4] = col[0]; m[index*4 + 1] = col[1]; m[index*4 + 2] = col[2]; m[index*4 + 3] = col[3];
}
inline void Matrix4::setColumn(int index, const Vector4& v)
{
m[index*4] = v.x; m[index*4 + 1] = v.y; m[index*4 + 2] = v.z; m[index*4 + 3] = v.w;
}
inline void Matrix4::setColumn(int index, const Vector3& v)
{
m[index*4] = v.x; m[index*4 + 1] = v.y; m[index*4 + 2] = v.z;
}
inline const float* Matrix4::get() const
{
return m;
}
inline Matrix4& Matrix4::identity()
{
m[0] = m[5] = m[10] = m[15] = 1.0f;
m[1] = m[2] = m[3] = m[4] = m[6] = m[7] = m[8] = m[9] = m[11] = m[12] = m[13] = m[14] = 0.0f;
return *this;
}
inline Matrix4 Matrix4::operator+(const Matrix4& rhs) const
{
return Matrix4(m[0]+rhs[0], m[1]+rhs[1], m[2]+rhs[2], m[3]+rhs[3],
m[4]+rhs[4], m[5]+rhs[5], m[6]+rhs[6], m[7]+rhs[7],
m[8]+rhs[8], m[9]+rhs[9], m[10]+rhs[10], m[11]+rhs[11],
m[12]+rhs[12], m[13]+rhs[13], m[14]+rhs[14], m[15]+rhs[15]);
}
inline Matrix4 Matrix4::operator-(const Matrix4& rhs) const
{
return Matrix4(m[0]-rhs[0], m[1]-rhs[1], m[2]-rhs[2], m[3]-rhs[3],
m[4]-rhs[4], m[5]-rhs[5], m[6]-rhs[6], m[7]-rhs[7],
m[8]-rhs[8], m[9]-rhs[9], m[10]-rhs[10], m[11]-rhs[11],
m[12]-rhs[12], m[13]-rhs[13], m[14]-rhs[14], m[15]-rhs[15]);
}
inline Matrix4& Matrix4::operator+=(const Matrix4& rhs)
{
m[0] += rhs[0]; m[1] += rhs[1]; m[2] += rhs[2]; m[3] += rhs[3];
m[4] += rhs[4]; m[5] += rhs[5]; m[6] += rhs[6]; m[7] += rhs[7];
m[8] += rhs[8]; m[9] += rhs[9]; m[10]+= rhs[10]; m[11]+= rhs[11];
m[12]+= rhs[12]; m[13]+= rhs[13]; m[14]+= rhs[14]; m[15]+= rhs[15];
return *this;
}
inline Matrix4& Matrix4::operator-=(const Matrix4& rhs)
{
m[0] -= rhs[0]; m[1] -= rhs[1]; m[2] -= rhs[2]; m[3] -= rhs[3];
m[4] -= rhs[4]; m[5] -= rhs[5]; m[6] -= rhs[6]; m[7] -= rhs[7];
m[8] -= rhs[8]; m[9] -= rhs[9]; m[10]-= rhs[10]; m[11]-= rhs[11];
m[12]-= rhs[12]; m[13]-= rhs[13]; m[14]-= rhs[14]; m[15]-= rhs[15];
return *this;
}
inline Vector4 Matrix4::operator*(const Vector4& rhs) const
{
return Vector4(m[0]*rhs.x + m[4]*rhs.y + m[8]*rhs.z + m[12]*rhs.w,
m[1]*rhs.x + m[5]*rhs.y + m[9]*rhs.z + m[13]*rhs.w,
m[2]*rhs.x + m[6]*rhs.y + m[10]*rhs.z + m[14]*rhs.w,
m[3]*rhs.x + m[7]*rhs.y + m[11]*rhs.z + m[15]*rhs.w);
}
inline Vector3 Matrix4::operator*(const Vector3& rhs) const
{
return Vector3(m[0]*rhs.x + m[4]*rhs.y + m[8]*rhs.z,
m[1]*rhs.x + m[5]*rhs.y + m[9]*rhs.z,
m[2]*rhs.x + m[6]*rhs.y + m[10]*rhs.z);
}
inline Matrix4 Matrix4::operator*(const Matrix4& n) const
{
return Matrix4(m[0]*n[0] + m[4]*n[1] + m[8]*n[2] + m[12]*n[3], m[1]*n[0] + m[5]*n[1] + m[9]*n[2] + m[13]*n[3], m[2]*n[0] + m[6]*n[1] + m[10]*n[2] + m[14]*n[3], m[3]*n[0] + m[7]*n[1] + m[11]*n[2] + m[15]*n[3],
m[0]*n[4] + m[4]*n[5] + m[8]*n[6] + m[12]*n[7], m[1]*n[4] + m[5]*n[5] + m[9]*n[6] + m[13]*n[7], m[2]*n[4] + m[6]*n[5] + m[10]*n[6] + m[14]*n[7], m[3]*n[4] + m[7]*n[5] + m[11]*n[6] + m[15]*n[7],
m[0]*n[8] + m[4]*n[9] + m[8]*n[10] + m[12]*n[11], m[1]*n[8] + m[5]*n[9] + m[9]*n[10] + m[13]*n[11], m[2]*n[8] + m[6]*n[9] + m[10]*n[10] + m[14]*n[11], m[3]*n[8] + m[7]*n[9] + m[11]*n[10] + m[15]*n[11],
m[0]*n[12] + m[4]*n[13] + m[8]*n[14] + m[12]*n[15], m[1]*n[12] + m[5]*n[13] + m[9]*n[14] + m[13]*n[15], m[2]*n[12] + m[6]*n[13] + m[10]*n[14] + m[14]*n[15], m[3]*n[12] + m[7]*n[13] + m[11]*n[14] + m[15]*n[15]);
}
inline Matrix4& Matrix4::operator*=(const Matrix4& rhs)
{
*this = *this * rhs;
return *this;
}
inline bool Matrix4::operator==(const Matrix4& n) const
{
return (m[0] == n[0]) && (m[1] == n[1]) && (m[2] == n[2]) && (m[3] == n[3]) &&
(m[4] == n[4]) && (m[5] == n[5]) && (m[6] == n[6]) && (m[7] == n[7]) &&
(m[8] == n[8]) && (m[9] == n[9]) && (m[10]== n[10]) && (m[11]== n[11]) &&
(m[12]== n[12]) && (m[13]== n[13]) && (m[14]== n[14]) && (m[15]== n[15]);
}
inline bool Matrix4::operator!=(const Matrix4& n) const
{
return (m[0] != n[0]) || (m[1] != n[1]) || (m[2] != n[2]) || (m[3] != n[3]) ||
(m[4] != n[4]) || (m[5] != n[5]) || (m[6] != n[6]) || (m[7] != n[7]) ||
(m[8] != n[8]) || (m[9] != n[9]) || (m[10]!= n[10]) || (m[11]!= n[11]) ||
(m[12]!= n[12]) || (m[13]!= n[13]) || (m[14]!= n[14]) || (m[15]!= n[15]);
}
inline float Matrix4::operator[](int index) const
{
return m[index];
}
inline float& Matrix4::operator[](int index)
{
return m[index];
}
inline Matrix4 operator-(const Matrix4& rhs)
{
return Matrix4(-rhs[0], -rhs[1], -rhs[2], -rhs[3], -rhs[4], -rhs[5], -rhs[6], -rhs[7], -rhs[8], -rhs[9], -rhs[10], -rhs[11], -rhs[12], -rhs[13], -rhs[14], -rhs[15]);
}
inline Matrix4 operator*(float s, const Matrix4& rhs)
{
return Matrix4(s*rhs[0], s*rhs[1], s*rhs[2], s*rhs[3], s*rhs[4], s*rhs[5], s*rhs[6], s*rhs[7], s*rhs[8], s*rhs[9], s*rhs[10], s*rhs[11], s*rhs[12], s*rhs[13], s*rhs[14], s*rhs[15]);
}
inline Vector4 operator*(const Vector4& v, const Matrix4& m)
{
return Vector4(v.x*m[0] + v.y*m[1] + v.z*m[2] + v.w*m[3], v.x*m[4] + v.y*m[5] + v.z*m[6] + v.w*m[7], v.x*m[8] + v.y*m[9] + v.z*m[10] + v.w*m[11], v.x*m[12] + v.y*m[13] + v.z*m[14] + v.w*m[15]);
}
inline Vector3 operator*(const Vector3& v, const Matrix4& m)
{
return Vector3(v.x*m[0] + v.y*m[1] + v.z*m[2], v.x*m[4] + v.y*m[5] + v.z*m[6], v.x*m[8] + v.y*m[9] + v.z*m[10]);
}
// END OF MATRIX4 INLINE //////////////////////////////////////////////////////
/*************************************************************/
/** MonochromeLib - monochrome graphic library for fx-9860G **/
/** MonochromeLib is free software **/
/** **/
/** @author Pierre "PierrotLL" Le Gall **/
/** @contact legallpierre89@gmail.com **/
/** **/
/** @file MonochromeLib.c **/
/** Code file of MonochromeLib **/
/** **/
/** @date 11-22-2011 **/
/*************************************************************/
#include "MonochromeLib.h"
#include <stdlib.h>
/******************************/
/** Dependencies management **/
/******************************/
#ifdef ML_ALL
#define ML_CLEAR_VRAM
#define ML_CLEAR_SCREEN
#define ML_DISPLAY_VRAM
#define ML_SET_CONTRAST
#define ML_GET_CONTRAST
#define ML_PIXEL
#define ML_POINT
#define ML_PIXEL_TEST
#define ML_LINE
#define ML_HORIZONTAL_LINE
#define ML_VERTICAL_LINE
#define ML_RECTANGLE
#define ML_POLYGON
#define ML_FILLED_POLYGON
#define ML_CIRCLE
#define ML_FILLED_CIRCLE
#define ML_ELLIPSE
#define ML_ELLIPSE_IN_RECT
#define ML_FILLED_ELLIPSE
#define ML_FILLED_ELLIPSE_IN_RECT
#define ML_HORIZONTAL_SCROLL
#define ML_VERTICAL_SCROLL
#define ML_BMP_OR
#define ML_BMP_AND
#define ML_BMP_XOR
#define ML_BMP_OR_CL
#define ML_BMP_AND_CL
#define ML_BMP_XOR_CL
#define ML_BMP_8_OR
#define ML_BMP_8_AND
#define ML_BMP_8_XOR
#define ML_BMP_8_OR_CL
#define ML_BMP_8_AND_CL
#define ML_BMP_8_XOR_CL
#define ML_BMP_16_OR
#define ML_BMP_16_AND
#define ML_BMP_16_XOR
#define ML_BMP_16_OR_CL
#define ML_BMP_16_AND_CL
#define ML_BMP_16_XOR_CL
#endif
#ifdef ML_POLYGON
#define ML_LINE
#endif
#ifdef ML_LINE
#define ML_PIXEL
#endif
#ifdef ML_POINT
#define ML_PIXEL
#define ML_RECTANGLE
#endif
#ifdef ML_RECTANGLE
#define ML_HORIZONTAL_LINE
#endif
#ifdef ML_FILLED_POLYGON
#define ML_HORIZONTAL_LINE
#endif
#ifdef ML_CIRCLE
#define ML_PIXEL
#endif
#ifdef ML_FILLED_CIRCLE
#define ML_HORIZONTAL_LINE
#endif
#ifdef ML_ELLIPSE_IN_RECT
#define ML_ELLIPSE
#endif
#ifdef ML_ELLIPSE
#define ML_PIXEL
#endif
#ifdef ML_FILLED_ELLIPSE_IN_RECT
#define ML_FILLED_ELLIPSE
#endif
#ifdef ML_FILLED_ELLIPSE
#define ML_HORIZONTAL_LINE
#endif
/***************/
/** Functions **/
/***************/
#define sgn(x) (x<0?-1:1)
#define rnd(x) ((int)(x+0.5))
//Thanks to Simon Lothar for this function
static int SysCallCode[] = {0xD201422B,0x60F20000,0x80010070};
static int (*SysCall)( int R4, int R5, int R6, int R7, int FNo ) = (void*)&SysCallCode;
char* ML_vram_adress()
{
return (char*)((*SysCall)(0, 0, 0, 0, 309));
}
#ifdef ML_CLEAR_VRAM
void ML_clear_vram()
{
int i, end, *pointer_long, vram;
char *pointer_byte;
vram = (int)ML_vram_adress();
end = 4-vram&3;
pointer_byte = (char*)vram;
for(i=0 ; i<end ; i++) pointer_byte[i] = 0;
pointer_long = (int*) (vram+end);
for(i=0 ; i<255 ; i++) pointer_long[i] = 0;
pointer_byte += 1020+end;
end = vram&3;
for(i=0 ; i<end ; i++) pointer_byte[i] = 0;
}
#endif
#ifdef ML_CLEAR_SCREEN
void ML_clear_screen()
{
char *LCD_register_selector = (char*)0xB4000000, *LCD_data_register = (char*)0xB4010000;
int i, j;
for(i=0 ; i<64 ; i++)
{
*LCD_register_selector = 4;
*LCD_data_register = i|192;
*LCD_register_selector = 4;
*LCD_data_register = 0;
*LCD_register_selector = 7;
for(j=0 ; j<16 ; j++) *LCD_data_register = 0;
}
}
#endif
#ifdef ML_DISPLAY_VRAM
void ML_display_vram()
{
char *LCD_register_selector = (char*)0xB4000000, *LCD_data_register = (char*)0xB4010000, *vram;
int i, j;
vram = ML_vram_adress();
for(i=0 ; i<64 ; i++)
{
*LCD_register_selector = 4;
*LCD_data_register = i|192;
*LCD_register_selector = 4;
*LCD_data_register = 0;
*LCD_register_selector = 7;
for(j=0 ; j<16 ; j++) *LCD_data_register = *vram++;
}
}
#endif
#ifdef ML_SET_CONTRAST
void ML_set_contrast(unsigned char contrast)
{
char *LCD_register_selector = (char*)0xB4000000, *LCD_data_register = (char*)0xB4010000;
*LCD_register_selector = 6;
*LCD_data_register = contrast;
}
#endif
#ifdef ML_GET_CONTRAST
unsigned char ML_get_contrast()
{
char *LCD_register_selector = (char*)0xB4000000, *LCD_data_register = (char*)0xB4010000;
*LCD_register_selector = 6;
return *LCD_data_register;
}
#endif
#ifdef ML_PIXEL
void ML_pixel(int x, int y, ML_Color color)
{
char* vram = ML_vram_adress();
if(x&~127 || y&~63) return;
switch(color)
{
case ML_BLACK:
vram[(y<<4)+(x>>3)] |= 128>>(x&7);
break;
case ML_WHITE:
vram[(y<<4)+(x>>3)] &= ~(128>>(x&7));
break;
case ML_XOR:
vram[(y<<4)+(x>>3)] ^= 128>>(x&7);
break;
case ML_CHECKER:
if(y&1^x&1) vram[(y<<4)+(x>>3)] &= ~(128>>(x&7));
else vram[(y<<4)+(x>>3)] |= 128>>(x&7);
break;
}
}
#endif
#ifdef ML_POINT
void ML_point(int x, int y, int width, ML_Color color)
{
if(width < 1) return;
if(width == 1) ML_pixel(x, y, color);
else
{
int padding, pair;
padding = width>>1;
pair = !(width&1);
ML_rectangle(x-padding+pair, y-padding+pair, x+padding, y+padding, 0, 0, color);
}
}
#endif
#ifdef ML_PIXEL_TEST
ML_Color ML_pixel_test(int x, int y)
{
char *vram, byte;
if(x&~127 || y&~63) return ML_TRANSPARENT;
vram = ML_vram_adress();
byte = 1<<(7-(x&7));
return (vram[(y<<4)+(x>>3)] & byte ? ML_BLACK : ML_WHITE);
}
#endif
#ifdef ML_LINE
void ML_line(int x1, int y1, int x2, int y2, ML_Color color)
{
int i, x, y, dx, dy, sx, sy, cumul;
x = x1;
y = y1;
dx = x2 - x1;
dy = y2 - y1;
sx = sgn(dx);
sy = sgn(dy);
dx = abs(dx);
dy = abs(dy);
ML_pixel(x, y, color);
if(dx > dy)
{
cumul = dx / 2;
for(i=1 ; i<dx ; i++)
{
x += sx;
cumul += dy;
if(cumul > dx)
{
cumul -= dx;
y += sy;
}
ML_pixel(x, y, color);
}
}
else
{
cumul = dy / 2;
for(i=1 ; i<dy ; i++)
{
y += sy;
cumul += dx;
if(cumul > dy)
{
cumul -= dy;
x += sx;
}
ML_pixel(x, y, color);
}
}
}
#endif
#ifdef ML_HORIZONTAL_LINE
void ML_horizontal_line(int y, int x1, int x2, ML_Color color)
{
int i;
char checker;
char* vram = ML_vram_adress();
if(y&~63 || (x1<0 && x2<0) || (x1>127 && x2>127)) return;
if(x1 > x2)
{
i = x1;
x1 = x2;
x2 = i;
}
if(x1 < 0) x1 = 0;
if(x2 > 127) x2 = 127;
switch(color)
{
case ML_BLACK:
if(x1>>3 != x2>>3)
{
vram[(y<<4)+(x1>>3)] |= 255 >> (x1&7);
vram[(y<<4)+(x2>>3)] |= 255 << 7-(x2&7);
for(i=(x1>>3)+1 ; i<x2>>3 ; i++)
vram[(y<<4) + i] = 255;
}
else vram[(y<<4)+(x1>>3)] |= (255>>(x1%8 + 7-x2%8))<<(7-(x2&7));
break;
case ML_WHITE:
if(x1>>3 != x2>>3)
{
vram[(y<<4)+(x1>>3)] &= 255 << 8-(x1&7);
vram[(y<<4)+(x2>>3)] &= 255 >> 1+(x2&7);
for(i=(x1>>3)+1 ; i<x2>>3 ; i++)
vram[(y<<4) + i] = 0;
}
else vram[(y<<4)+(x1>>3)] &= (255<<8-(x1&7)) | (255>>1+(x2&7));
break;
case ML_XOR:
if(x1>>3 != x2>>3)
{
vram[(y<<4)+(x1>>3)] ^= 255 >> (x1&7);
vram[(y<<4)+(x2>>3)] ^= 255 << 7-(x2&7);
for(i=(x1>>3)+1 ; i<(x2>>3) ; i++)
vram[(y<<4) + i] ^= 255;
}
else vram[(y<<4)+(x1>>3)] ^= (255>>((x1&7) + 7-(x2&7)))<<(7-(x2&7));
break;
case ML_CHECKER:
checker = (y&1 ? 85 : 170);
if(x1>>3 != x2>>3)
{
vram[(y<<4)+(x1>>3)] &= 255 << 8-(x1&7);
vram[(y<<4)+(x2>>3)] &= 255 >> 1+(x2&7);
vram[(y<<4)+(x1>>3)] |= checker & 255>>(x1&7);
vram[(y<<4)+(x2>>3)] |= checker & 255<<7-(x2&7);
for(i=(x1>>3)+1 ; i<x2>>3 ; i++)
vram[(y<<4) + i] = checker;
}
else
{
vram[(y<<4)+(x1>>3)] &= (255<<8-(x1&7)) | (255>>1+(x2&7));
vram[(y<<4)+(x1>>3)] |= checker & (255>>(x1%8 + 7-x2%8))<<(7-(x2&7));
}
break;
}
}
#endif
#ifdef ML_VERTICAL_LINE
void ML_vertical_line(int x, int y1, int y2, ML_Color color)
{
int i, j;
char checker, byte, *vram = ML_vram_adress();
if(x&~127 || (y1<0 && y2<0) || (y1>63 && y2>63)) return;
if(y1 > y2)
{
int tmp = y1;
y1 = y2;
y2 = tmp;
}
if(y1 < 0) y1 = 0;
if(y2 > 63) y2 = 63;
i = (y1<<4)+(x>>3);
j = (y2<<4)+(x>>3);
switch(color)
{
case ML_BLACK:
byte = 128>>(x&7);
for( ; i<=j ; i+=16)
vram[i] |= byte;
break;
case ML_WHITE:
byte = ~(128>>(x&7));
for( ; i<=j ; i+=16)
vram[i] &= byte;
break;
case ML_XOR:
byte = 128>>(x&7);
for( ; i<=j ; i+=16)
vram[i] ^= byte;
break;
case ML_CHECKER:
byte = 128>>(x&7);
checker = y1&1^x&1;
for( ; i<=j ; i+=16)
{
if(checker) vram[i] &= ~byte;
else vram[i] |= byte;
checker = !checker;
}
break;
}
}
#endif
#ifdef ML_RECTANGLE
void ML_rectangle(int x1, int y1, int x2, int y2, int border_width, ML_Color border_color, ML_Color fill_color)
{
int i;
if(x1 > x2)
{
i = x1;
x1 = x2;
x2 = i;
}
if(y1 > y2)
{
i = y1;
y1 = y2;
y2 = i;
}
if(border_width > (x2-x1)/2+1) border_width = (x2-x1)/2+1;
if(border_width > (y2-y1)/2+1) border_width = (y2-y1)/2+1;
if(border_color != ML_TRANSPARENT && border_width > 0)
{
for(i=0 ; i<border_width ; i++)
{
ML_horizontal_line(y1+i, x1, x2, border_color);
ML_horizontal_line(y2-i, x1, x2, border_color);
}
for(i=y1+border_width ; i<=y2-border_width ; i++)
{
ML_horizontal_line(i, x1, x1+border_width-1, border_color);
ML_horizontal_line(i, x2-border_width+1, x2, border_color);
}
}
if(fill_color != ML_TRANSPARENT)
{
for(i=y1+border_width ; i<=y2-border_width ; i++)
ML_horizontal_line(i, x1+border_width, x2-border_width, fill_color);
}
}
#endif
#ifdef ML_POLYGON
void ML_polygon(const int *x, const int *y, int nb_vertices, ML_Color color)
{
int i;
if(nb_vertices < 1) return;
for(i=0 ; i<nb_vertices-1 ; i++)
ML_line(x[i], y[i], x[i+1], y[i+1], color);
ML_line(x[i], y[i], x[0], y[0], color);
}
#endif
#ifdef ML_FILLED_POLYGON
static int ML_filled_polygon_quicksord_partition(int *t, int p, int r)
{
int i, j, x, tmp;
j = p - 1;
x = t[r];
for(i=p ; i<r ; i++)
{
if(x > t[i])
{
j++;
tmp = t[j];
t[j] = t[i];
t[i] = tmp;
}
}
t[r] = t[j+1];
t[j+1] = x;
return j + 1;
}
static void ML_filled_polygon_quicksord(int* t, int p, int r)
{
int q;
if(p < r)
{
q = ML_filled_polygon_quicksord_partition(t, p, r);
ML_filled_polygon_quicksord(t, p, q-1);
ML_filled_polygon_quicksord(t, q+1, r);
}
}
void ML_filled_polygon(const int *x, const int *y, int nb_vertices, ML_Color color)
{
int i, j, dx, dy, ymin, ymax;
int *cut_in_line, nb_cut;
if(nb_vertices < 3) return;
cut_in_line = malloc(nb_vertices*sizeof(int));
if(!cut_in_line) return;
ymin = ymax = y[0];
for(i=1 ; i<nb_vertices ; i++)
{
if(y[i] < ymin) ymin = y[i];
if(y[i] > ymax) ymax = y[i];
}
for(i=ymin ; i<=ymax ; i++)
{
nb_cut = 0;
for(j=0 ; j<nb_vertices ; j++)
{
if((y[j]<=i && y[(j+1)%nb_vertices]>=i) || (y[j]>=i && y[(j+1)%nb_vertices]<=i))
{
dy = abs(y[j]-y[(j+1)%nb_vertices]);
if(dy)
{
dx = x[(j+1)%nb_vertices]-x[j];
cut_in_line[nb_cut] = x[j] + rnd(abs(i-y[j]+sgn(i-y[j])/2)*dx/dy);
nb_cut++;
}
}
}
ML_filled_polygon_quicksord(cut_in_line, 0, nb_cut-1);
j = 0;
while(j<nb_cut-2 && cut_in_line[j]==cut_in_line[j+1]) j++;
while(j < nb_cut)
{
if(j == nb_cut-1) ML_horizontal_line(i, cut_in_line[j-1]+1, cut_in_line[j], color);
else
{
dx = 1;
while(j+dx<nb_cut-1 && cut_in_line[j+dx]==cut_in_line[j+dx+1]) dx++;
ML_horizontal_line(i, cut_in_line[j], cut_in_line[j+dx], color);
j += dx;
}
j++;
}
}
free(cut_in_line);
}
#endif
#ifdef ML_CIRCLE
void ML_circle(int x, int y, int radius, ML_Color color)
{
int plot_x, plot_y, d;
if(radius < 0) return;
plot_x = 0;
plot_y = radius;
d = 1 - radius;
ML_pixel(x, y+plot_y, color);
if(radius)
{
ML_pixel(x, y-plot_y, color);
ML_pixel(x+plot_y, y, color);
ML_pixel(x-plot_y, y, color);
}
while(plot_y > plot_x)
{
if(d < 0)
d += 2*plot_x+3;
else
{
d += 2*(plot_x-plot_y)+5;
plot_y--;
}
plot_x++;
if(plot_y >= plot_x)
{
ML_pixel(x+plot_x, y+plot_y, color);
ML_pixel(x-plot_x, y+plot_y, color);
ML_pixel(x+plot_x, y-plot_y, color);
ML_pixel(x-plot_x, y-plot_y, color);
}
if(plot_y > plot_x)
{
ML_pixel(x+plot_y, y+plot_x, color);
ML_pixel(x-plot_y, y+plot_x, color);
ML_pixel(x+plot_y, y-plot_x, color);
ML_pixel(x-plot_y, y-plot_x, color);
}
}
}
#endif
#ifdef ML_FILLED_CIRCLE
void ML_filled_circle(int x, int y, int radius, ML_Color color)
{
int plot_x, plot_y, d;
if(radius < 0) return;
plot_x = 0;
plot_y = radius;
d = 1 - radius;
ML_horizontal_line(y, x-plot_y, x+plot_y, color);
while(plot_y > plot_x)
{
if(d < 0)
d += 2*plot_x+3;
else {
d += 2*(plot_x-plot_y)+5;
plot_y--;
ML_horizontal_line(y+plot_y+1, x-plot_x, x+plot_x, color);
ML_horizontal_line(y-plot_y-1, x-plot_x, x+plot_x, color);
}
plot_x++;
if(plot_y >= plot_x)
{
ML_horizontal_line(y+plot_x, x-plot_y, x+plot_y, color);
ML_horizontal_line(y-plot_x, x-plot_y, x+plot_y, color);
}
}
}
#endif
#ifdef ML_ELLIPSE
void ML_ellipse(int x, int y, int radius1, int radius2, ML_Color color)
{
int plot_x, plot_y;
float d1, d2;
if(radius1 < 1 || radius2 < 1) return;
plot_x = 0;
plot_y = radius2;
d1 = radius2*radius2 - radius1*radius1*radius2 + radius1*radius1/4;
ML_pixel(x, y+plot_y, color);
ML_pixel(x, y-plot_y, color);
while(radius1*radius1*(plot_y-.5) > radius2*radius2*(plot_x+1))
{
if(d1 < 0)
{
d1 += radius2*radius2*(2*plot_x+3);
plot_x++;
} else {
d1 += radius2*radius2*(2*plot_x+3) + radius1*radius1*(-2*plot_y+2);
plot_x++;
plot_y--;
}
ML_pixel(x+plot_x, y+plot_y, color);
ML_pixel(x-plot_x, y+plot_y, color);
ML_pixel(x+plot_x, y-plot_y, color);
ML_pixel(x-plot_x, y-plot_y, color);
}
d2 = radius2*radius2*(plot_x+.5)*(plot_x+.5) + radius1*radius1*(plot_y-1)*(plot_y-1) - radius1*radius1*radius2*radius2;
while(plot_y > 0)
{
if(d2 < 0)
{
d2 += radius2*radius2*(2*plot_x+2) + radius1*radius1*(-2*plot_y+3);
plot_y--;
plot_x++;
} else {
d2 += radius1*radius1*(-2*plot_y+3);
plot_y--;
}
ML_pixel(x+plot_x, y+plot_y, color);
ML_pixel(x-plot_x, y+plot_y, color);
if(plot_y > 0)
{
ML_pixel(x+plot_x, y-plot_y, color);
ML_pixel(x-plot_x, y-plot_y, color);
}
}
}
#endif
#ifdef ML_ELLIPSE_IN_RECT
void ML_ellipse_in_rect(int x1, int y1, int x2, int y2, ML_Color color)
{
int radius1, radius2;
if(x1 > x2)
{
int tmp = x1;
x1 = x2;
x2 = tmp;
}
if(y1 > y2)
{
int tmp = y1;
y1 = y2;
y2 = tmp;
}
radius1 = (x2-x1)/2;
radius2 = (y2-y1)/2;
ML_ellipse(x1+radius1, y1+radius2, radius1, radius2, color);
}
#endif
#ifdef ML_FILLED_ELLIPSE
void ML_filled_ellipse(int x, int y, int radius1, int radius2, ML_Color color)
{
int plot_x, plot_y;
float d1, d2;
if(radius1 < 1 || radius2 < 1) return;
plot_x = 0;
plot_y = radius2;
d1 = radius2*radius2 - radius1*radius1*radius2 + radius1*radius1/4;
while(radius1*radius1*(plot_y-.5) > radius2*radius2*(plot_x+1))
{
if(d1 < 0)
{
d1 += radius2*radius2*(2*plot_x+3);
plot_x++;
} else {
d1 += radius2*radius2*(2*plot_x+3) + radius1*radius1*(-2*plot_y+2);
ML_horizontal_line(y+plot_y, x-plot_x, x+plot_x, color);
ML_horizontal_line(y-plot_y, x-plot_x, x+plot_x, color);
plot_x++;
plot_y--;
}
}
ML_horizontal_line(y+plot_y, x-plot_x, x+plot_x, color);
ML_horizontal_line(y-plot_y, x-plot_x, x+plot_x, color);
d2 = radius2*radius2*(plot_x+.5)*(plot_x+.5) + radius1*radius1*(plot_y-1)*(plot_y-1) - radius1*radius1*radius2*radius2;
while(plot_y > 0)
{
if(d2 < 0)
{
d2 += radius2*radius2*(2*plot_x+2) + radius1*radius1*(-2*plot_y+3);
plot_y--;
plot_x++;
} else {
d2 += radius1*radius1*(-2*plot_y+3);
plot_y--;
}
ML_horizontal_line(y+plot_y, x-plot_x, x+plot_x, color);
if(plot_y > 0)
ML_horizontal_line(y-plot_y, x-plot_x, x+plot_x, color);
}
}
#endif
#ifdef ML_FILLED_ELLIPSE_IN_RECT
void ML_filled_ellipse_in_rect(int x1, int y1, int x2, int y2, ML_Color color)
{
int radius1, radius2;
if(x1 > x2)
{
int tmp = x1;
x1 = x2;
x2 = tmp;
}
if(y1 > y2)
{
int tmp = y1;
y1 = y2;
y2 = tmp;
}
radius1 = (x2-x1)/2;
radius2 = (y2-y1)/2;
ML_filled_ellipse(x1+radius1, y1+radius2, radius1, radius2, color);
}
#endif
#ifdef ML_HORIZONTAL_SCROLL
void ML_horizontal_scroll(int scroll)
{
int i, j;
char line[16], shift, *vram;
unsigned char next;
unsigned short word;
vram = ML_vram_adress();
scroll %= 128;
shift = 8-(scroll&7);
for(i=0 ; i<64 ; i++)
{
for(j=0 ; j<16 ; j++) line[j] = vram[(i<<4)+((j-(scroll>>3)+15)&15)];
next = line[15];
vram[(i<<4)+15] = 0;
for(j=15 ; j>0 ; j--)
{
word = next << shift;
next = line[j-1];
vram[(i<<4)+j] |= *((char*)&word+1);
vram[(i<<4)+j-1] = *((char*)&word);
}
word = next << shift;
vram[(i<<4)] |= *((char*)&word+1);
vram[(i<<4)+15] |= *((char*)&word);
}
}
#endif
#ifdef ML_VERTICAL_SCROLL
void ML_vertical_scroll(int scroll)
{
int i, j;
char column[64], *vram = ML_vram_adress();
scroll %= 64;
for(i=0 ; i<16 ; i++)
{
for(j=0 ; j<64 ; j++) column[j] = vram[(j<<4)+i];
for(j=0 ; j<64 ; j++) vram[(j<<4)+i] = column[(j-scroll+64)&63];
}
}
#endif
#ifdef ML_BMP_OR
void ML_bmp_or(const unsigned char *bmp, int x, int y, int width, int height)
{
unsigned short line;
char shift, *screen, *p=(char*)&line;
int i, j, begin=0, end=height, real_width=(width-1>>3<<3)+8;
if(!bmp || x<0 || x>128-width || y<1-height || y>63 || width<1 || height<1) return;
if(y < 0) begin = -y;
if(y+height > 64) end = 64-y;
shift = 8-(x&7);
screen = ML_vram_adress()+(y+begin<<4)+(x>>3);
for(i=begin ; i<end ; i++)
{
for(j=0 ; j<width-1>>3 ; j++)
{
line = bmp[i*(real_width>>3)+j]<<shift;
screen[j] |= *p;
if(shift!=8) screen[j+1] |= *(p+1);
}
line = (bmp[i*(real_width>>3)+j] & -1<<(real_width-width))<<shift;
screen[j] |= *p;
if(shift!=8 && x+real_width<129) screen[j+1] |= *(p+1);
screen += 16;
}
}
#endif
#ifdef ML_BMP_AND
void ML_bmp_and(const unsigned char *bmp, int x, int y, int width, int height)
{
unsigned short line;
char shift, *screen, *p=(char*)&line;
int i, j, begin=0, end=height, real_width=(width-1>>3<<3)+8;
if(!bmp || x<0 || x>128-width || y<1-height || y>63 || width<1 || height<1) return;
if(y < 0) begin = -y;
if(y+height > 64) end = 64-y;
shift = 8-(x&7);
screen = ML_vram_adress()+(y+begin<<4)+(x>>3);
for(i=begin ; i<end ; i++)
{
for(j=0 ; j<width-1>>3 ; j++)
{
line = ~((unsigned char)~bmp[i*(real_width>>3)+j]<<shift);
screen[j] &= *p;
if(shift!=8) screen[j+1] &= *(p+1);
}
line = ~((unsigned char)~(bmp[i*(real_width>>3)+j] | (unsigned char)-1>>8-(width&7))<<shift);
screen[j] &= *p;
if(shift!=8 && x+real_width<129) screen[j+1] &= *(p+1);
screen += 16;
}
}
#endif
#ifdef ML_BMP_XOR
void ML_bmp_xor(const unsigned char *bmp, int x, int y, int width, int height)
{
unsigned short line;
char shift, *screen, *p=(char*)&line;
int i, j, begin=0, end=height, real_width=(width-1>>3<<3)+8;
if(!bmp || x<0 || x>128-width || y<1-height || y>63 || width<1 || height<1) return;
if(y < 0) begin = -y;
if(y+height > 64) end = 64-y;
shift = 8-(x&7);
screen = ML_vram_adress()+(y+begin<<4)+(x>>3);
for(i=begin ; i<end ; i++)
{
for(j=0 ; j<width-1>>3 ; j++)
{
line = bmp[i*(real_width>>3)+j]<<shift;
screen[j] ^= *p;
if(shift!=8) screen[j+1] ^= *(p+1);
}
line = (bmp[i*(real_width>>3)+j] & -1<<(real_width-width))<<shift;
screen[j] ^= *p;
if(shift!=8 && x+real_width<129) screen[j+1] ^= *(p+1);
screen += 16;
}
}
#endif
#ifdef ML_BMP_OR_CL
void ML_bmp_or_cl(const unsigned char *bmp, int x, int y, int width, int height)
{
unsigned short line;
char shift, *screen, *p;
int i, j, real_width, begin_x, end_x, begin_y, end_y;
char bool1=1, bool2=1, bool3;
if(!bmp || x<1-width || x>127 || y<1-height || y>63 || height<1 || width<1) return;
p = (char*)&line;
real_width = (width-1>>3<<3)+8;
if(y < 0) begin_y = -y;
else begin_y = 0;
if(y+height > 64) end_y = 64-y;
else end_y = height;
shift = 8-(x&7);
if(x<0)
{
begin_x = -x>>3;
if(shift != 8) bool1 = 0;
} else begin_x = 0;
if(x+real_width > 128) end_x = 15-(x>>3), bool2 = 0;
else end_x = real_width-1>>3;
bool3 = (end_x == real_width-1>>3);
screen = ML_vram_adress()+(y+begin_y<<4)+(x>>3);
for(i=begin_y ; i<end_y ; i++)
{
if(begin_x < end_x)
{
line = bmp[i*(real_width>>3)+begin_x] << shift;
if(bool1) screen[begin_x] |= *p;
if(shift!=8) screen[begin_x+1] |= *(p+1);
for(j=begin_x+1 ; j<end_x ; j++)
{
line = bmp[i*(real_width>>3)+j] << shift;
screen[j] |= *p;
if(shift!=8) screen[j+1] |= *(p+1);
}
}
line = bmp[i*(real_width>>3)+end_x];
if(bool3) line &= -1<<real_width-width;
line <<= shift;
if(begin_x < end_x || bool1) screen[end_x] |= *p;
if(bool2) screen[end_x+1] |= *(p+1);
screen += 16;
}
}
#endif
#ifdef ML_BMP_AND_CL
void ML_bmp_and_cl(const unsigned char *bmp, int x, int y, int width, int height)
{
unsigned short line;
char shift, *screen, *p;
int i, j, real_width, begin_x, end_x, begin_y, end_y;
char bool1=1, bool2=1, bool3;
if(!bmp || x<1-width || x>127 || y<1-height || y>63 || height<1 || width<1) return;
p = (char*)&line;
real_width = (width-1>>3<<3)+8;
if(y < 0) begin_y = -y;
else begin_y = 0;
if(y+height > 64) end_y = 64-y;
else end_y = height;
shift = 8-(x&7);
if(x<0)
{
begin_x = -x>>3;
if(shift != 8) bool1 = 0;
} else begin_x = 0;
if(x+real_width > 128) end_x = 15-(x>>3), bool2 = 0;
else end_x = real_width-1>>3;
bool3 = (end_x == real_width-1>>3);
screen = ML_vram_adress()+(y+begin_y<<4)+(x>>3);
for(i=begin_y ; i<end_y ; i++)
{
if(begin_x < end_x)
{
line = ~((unsigned char)~bmp[i*(real_width>>3)+begin_x]<<shift);
if(bool1) screen[begin_x] &= *p;
if(shift!=8) screen[begin_x+1] &= *(p+1);
for(j=begin_x+1 ; j<end_x ; j++)
{
line = ~((unsigned char)~bmp[i*(real_width>>3)+j]<<shift);
screen[j] &= *p;
if(shift!=8) screen[j+1] &= *(p+1);
}
}
line = (unsigned char)~bmp[i*(real_width>>3)+end_x];
if(bool3) line &= -1<<real_width-width;
line = ~(line << shift);
if(begin_x < end_x || bool1) screen[end_x] &= *p;
if(bool2) screen[end_x+1] &= *(p+1);
screen += 16;
}
}
#endif
#ifdef ML_BMP_XOR_CL
void ML_bmp_xor_cl(const unsigned char *bmp, int x, int y, int width, int height)
{
unsigned short line;
char shift, *screen, *p;
int i, j, real_width, begin_x, end_x, begin_y, end_y;
char bool1=1, bool2=1, bool3;
if(!bmp || x<1-width || x>127 || y<1-height || y>63 || height<1 || width<1) return;
p = (char*)&line;
real_width = (width-1>>3<<3)+8;
if(y < 0) begin_y = -y;
else begin_y = 0;
if(y+height > 64) end_y = 64-y;
else end_y = height;
shift = 8-(x&7);
if(x<0)
{
begin_x = -x>>3;
if(shift != 8) bool1 = 0;
} else begin_x = 0;
if(x+real_width > 128) end_x = 15-(x>>3), bool2 = 0;
else end_x = real_width-1>>3;
bool3 = (end_x == real_width-1>>3);
screen = ML_vram_adress()+(y+begin_y<<4)+(x>>3);
for(i=begin_y ; i<end_y ; i++)
{
if(begin_x < end_x)
{
line = bmp[i*(real_width>>3)+begin_x] << shift;
if(bool1) screen[begin_x] ^= *p;
if(shift!=8) screen[begin_x+1] ^= *(p+1);
for(j=begin_x+1 ; j<end_x ; j++)
{
line = bmp[i*(real_width>>3)+j] << shift;
screen[j] ^= *p;
if(shift!=8) screen[j+1] ^= *(p+1);
}
}
line = bmp[i*(real_width>>3)+end_x];
if(bool3) line &= -1<<real_width-width;
line <<= shift;
if(begin_x < end_x || bool1) screen[end_x] ^= *p;
if(bool2) screen[end_x+1] ^= *(p+1);
screen += 16;
}
}
#endif
#ifdef ML_BMP_8_OR
void ML_bmp_8_or(const unsigned char *bmp, int x, int y)
{
unsigned short line;
char i, shift, begin=0, end=8, *screen, *p=(char*)&line;
if(!bmp || x<0 || x>120 || y<-7 || y>63) return;
if(y < 0) begin = -y;
if(y > 56) end = 64-y;
shift = 8-(x&7);
screen = ML_vram_adress()+(y+begin<<4)+(x>>3);
for(i=begin ; i<end ; i++)
{
line = bmp[i]<<shift;
screen[0] |= *p;
if(shift!=8) screen[1] |= *(p+1);
screen += 16;
}
}
#endif
#ifdef ML_BMP_8_AND
void ML_bmp_8_and(const unsigned char *bmp, int x, int y)
{
unsigned short line;
char i, shift, begin=0, end=8, *screen, *p=(char*)&line;
if(!bmp || x<0 || x>120 || y<-7 || y>63) return;
if(y < 0) begin = -y;
if(y > 56) end = 64-y;
shift = 8-(x&7);
screen = ML_vram_adress()+(y+begin<<4)+(x>>3);
for(i=begin ; i<end ; i++)
{
line = ~((unsigned char)~bmp[i]<<shift);
screen[0] &= *p;
if(shift!=8) screen[1] &= *(p+1);
screen += 16;
}
}
#endif
#ifdef ML_BMP_8_XOR
void ML_bmp_8_xor(const unsigned char *bmp, int x, int y)
{
unsigned short line;
char i, shift, begin=0, end=8, *screen, *p=(char*)&line;
if(!bmp || x<0 || x>120 || y<-7 || y>63) return;
if(y < 0) begin = -y;
if(y > 56) end = 64-y;
shift = 8-(x&7);
screen = ML_vram_adress()+(y+begin<<4)+(x>>3);
for(i=begin ; i<end ; i++)
{
line = bmp[i]<<shift;
screen[0] ^= *p;
if(shift<8) screen[1] ^= *(p+1);
screen += 16;
}
}
#endif
#ifdef ML_BMP_8_OR_CL
void ML_bmp_8_or_cl(const unsigned char *bmp, int x, int y)
{
unsigned short line;
char i, shift, begin=0, end=8, bool1=1, bool2=1, *screen, *p=(char*)&line;
if(!bmp || x<-7 || x>127 || y<-7 || y>63) return;
if(y < 0) begin = -y;
if(y > 56) end = 64-y;
shift = 8-(x&7);
if(x < 0) bool1 = 0;
if(x>120 || shift==8) bool2 = 0;
screen = ML_vram_adress()+(y+begin<<4)+(x>>3);
for(i=begin ; i<end ; i++)
{
line = bmp[i]<<shift;
if(bool1) screen[0] |= *p;
if(bool2) screen[1] |= *(p+1);
screen += 16;
}
}
#endif
#ifdef ML_BMP_8_AND_CL
void ML_bmp_8_and_cl(const unsigned char *bmp, int x, int y)
{
unsigned short line;
char i, shift, begin=0, end=8, bool1=1, bool2=1, *screen, *p=(char*)&line;
if(!bmp || x<-7 || x>127 || y<-7 || y>63) return;
if(y < 0) begin = -y;
if(y > 56) end = 64-y;
shift = 8-(x&7);
if(x < 0) bool1 = 0;
if(x>120 || shift==8) bool2 = 0;
screen = ML_vram_adress()+(y+begin<<4)+(x>>3);
for(i=begin ; i<end ; i++)
{
line = ~((unsigned char)~bmp[i]<<shift);
if(bool1) screen[0] &= *p;
if(bool2) screen[1] &= *(p+1);
screen += 16;
}
}
#endif
#ifdef ML_BMP_8_XOR_CL
void ML_bmp_8_xor_cl(const unsigned char *bmp, int x, int y)
{
unsigned short line;
char i, shift, begin=0, end=8, bool1=1, bool2=1, *screen, *p=(char*)&line;
if(!bmp || x<-7 || x>127 || y<-7 || y>63) return;
if(y < 0) begin = -y;
if(y > 56) end = 64-y;
shift = 8-(x&7);
if(x < 0) bool1 = 0;
if(x>120 || shift==8) bool2 = 0;
screen = ML_vram_adress()+(y+begin<<4)+(x>>3);
for(i=begin ; i<end ; i++)
{
line = bmp[i]<<shift;
if(bool1) screen[0] ^= *p;
if(bool2) screen[1] ^= *(p+1);
screen += 16;
}
}
#endif
#ifdef ML_BMP_16_OR
void ML_bmp_16_or(const unsigned short *bmp, int x, int y)
{
unsigned long line;
char i, shift, begin=0, end=16, *screen, *p=(char*)&line+1;
if(!bmp || x<0 || x>112 || y<-15 || y>63) return;
if(y < 0) begin = -y;
if(y > 48) end = 64-y;
shift = 8-(x&7);
screen = ML_vram_adress()+(y+begin<<4)+(x>>3);
for(i=begin ; i<end ; i++)
{
line = bmp[i]<<shift;
screen[0] |= *p;
screen[1] |= *(p+1);
if(shift!=8) screen[2] |= *(p+2);
screen += 16;
}
}
#endif
#ifdef ML_BMP_16_AND
void ML_bmp_16_and(const unsigned short *bmp, int x, int y)
{
unsigned long line;
char i, shift, begin=0, end=16, *screen, *p=(char*)&line+1;
if(!bmp || x<0 || x>112 || y<-15 || y>63) return;
if(y < 0) begin = -y;
if(y > 48) end = 64-y;
shift = 8-(x&7);
screen = ML_vram_adress()+(y+begin<<4)+(x>>3);
for(i=begin ; i<end ; i++)
{
line = ~((unsigned short)~bmp[i]<<shift);
screen[0] &= *p;
screen[1] &= *(p+1);
if(shift!=8) screen[2] &= *(p+2);
screen += 16;
}
}
#endif
#ifdef ML_BMP_16_XOR
void ML_bmp_16_xor(const unsigned short *bmp, int x, int y)
{
unsigned long line;
char i, shift, begin=0, end=16, *screen, *p=(char*)&line+1;
if(!bmp || x<0 || x>112 || y<-15 || y>63) return;
if(y < 0) begin = -y;
if(y > 48) end = 64-y;
shift = 8-(x&7);
screen = ML_vram_adress()+(y+begin<<4)+(x>>3);
for(i=begin ; i<end ; i++)
{
line = bmp[i]<<shift;
screen[0] ^= *p;
screen[1] ^= *(p+1);
if(shift!=8) screen[2] ^= *(p+2);
screen += 16;
}
}
#endif
#ifdef ML_BMP_16_OR_CL
void ML_bmp_16_or_cl(const unsigned short *bmp, int x, int y)
{
unsigned long line;
char i, shift, begin=0, end=16, bool1=1, bool2=1, bool3=1, *screen, *p=(char*)&line+1;
if(!bmp || x<-15 || x>127 || y<-15 || y>63) return;
if(y < 0) begin = -y;
if(y > 48) end = 64-y;
shift = 8-(x&7);
if(x < 0) bool1 = 0;
if(x<-8 || x>119) bool2 = 0;
if(x>111 || shift==8) bool3 = 0;
screen = ML_vram_adress()+(y+begin<<4)+(x>>3);
for(i=begin ; i<end ; i++)
{
line = bmp[i]<<shift;
if(bool1) screen[0] |= *p;
if(bool2) screen[1] |= *(p+1);
if(bool3) screen[2] |= *(p+2);
screen += 16;
}
}
#endif
#ifdef ML_BMP_16_AND_CL
void ML_bmp_16_and_cl(const unsigned short *bmp, int x, int y)
{
unsigned long line;
char i, shift, begin=0, end=16, bool1=1, bool2=1, bool3=1, *screen, *p=(char*)&line+1;
if(!bmp || x<-15 || x>127 || y<-15 || y>63) return;
if(y < 0) begin = -y;
if(y > 48) end = 64-y;
shift = 8-(x&7);
if(x < 0) bool1 = 0;
if(x<-8 || x>119) bool2 = 0;
if(x>111 || shift==8) bool3 = 0;
screen = ML_vram_adress()+(y+begin<<4)+(x>>3);
for(i=begin ; i<end ; i++)
{
line = ~((unsigned short)~bmp[i]<<shift);
if(bool1) screen[0] &= *p;
if(bool2) screen[1] &= *(p+1);
if(bool3) screen[2] &= *(p+2);
screen += 16;
}
}
#endif
#ifdef ML_BMP_16_XOR_CL
void ML_bmp_16_xor_cl(const unsigned short *bmp, int x, int y)
{
unsigned long line;
char i, shift, begin=0, end=16, bool1=1, bool2=1, bool3=1, *screen, *p=(char*)&line+1;
if(!bmp || x<-15 || x>127 || y<-15 || y>63) return;
if(y < 0) begin = -y;
if(y > 48) end = 64-y;
shift = 8-(x&7);
if(x < 0) bool1 = 0;
if(x<-8 || x>119) bool2 = 0;
if(x>111 || shift==8) bool3 = 0;
screen = ML_vram_adress()+(y+begin<<4)+(x>>3);
for(i=begin ; i<end ; i++)
{
line = bmp[i]<<shift;
if(bool1) screen[0] ^= *p;
if(bool2) screen[1] ^= *(p+1);
if(bool3) screen[2] ^= *(p+2);
screen += 16;
}
}
#endif
/*************************************************************/
/** MonochromeLib - monochrome graphic library for fx-9860G **/
/** MonochromeLib is free software **/
/** **/
/** @author Pierre "PierrotLL" Le Gall **/
/** @contact legallpierre89@gmail.com **/
/** **/
/** @file MonochromeLib.h **/
/** Include header for MonochromeLib **/
/** **/
/** @date 11-22-2011 **/
/*************************************************************/
#ifndef MONOCHROMELIB
#define MONOCHROMELIB
/****************************************************/
/** uncomment #define of functions you want to use **/
/****************************************************/
#define ML_ALL //Auto define all functions
// #define ML_CLEAR_VRAM
// #define ML_CLEAR_SCREEN
// #define ML_DISPLAY_VRAM
// #define ML_SET_CONTRAST
// #define ML_GET_CONTRAST
// #define ML_PIXEL
// #define ML_POINT
// #define ML_PIXEL_TEST
// #define ML_LINE
// #define ML_HORIZONTAL_LINE
// #define ML_VERTICAL_LINE
// #define ML_RECTANGLE
// #define ML_POLYGON
// #define ML_FILLED_POLYGON
// #define ML_CIRCLE
// #define ML_FILLED_CIRCLE
// #define ML_ELLIPSE
// #define ML_ELLIPSE_IN_RECT
// #define ML_FILLED_ELLIPSE
// #define ML_FILLED_ELLIPSE_IN_RECT
// #define ML_HORIZONTAL_SCROLL
// #define ML_VERTICAL_SCROLL
// #define ML_BMP_OR
// #define ML_BMP_AND
// #define ML_BMP_XOR
// #define ML_BMP_OR_CL
// #define ML_BMP_AND_CL
// #define ML_BMP_XOR_CL
// #define ML_BMP_8_OR
// #define ML_BMP_8_AND
// #define ML_BMP_8_XOR
// #define ML_BMP_8_OR_CL
// #define ML_BMP_8_AND_CL
// #define ML_BMP_8_XOR_CL
// #define ML_BMP_16_OR
// #define ML_BMP_16_AND
// #define ML_BMP_16_XOR
// #define ML_BMP_16_OR_CL
// #define ML_BMP_16_AND_CL
// #define ML_BMP_16_XOR_CL
/**************************/
/** Functions prototypes **/
/**************************/
#ifdef __cplusplus
extern "C" {
#endif
#define ML_SCREEN_WIDTH 128
#define ML_SCREEN_HEIGHT 64
#define ML_CONTRAST_MIN 130
#define ML_CONTRAST_NORMAL 168
#define ML_CONTRAST_MAX 190
typedef enum {ML_TRANSPARENT=-1, ML_WHITE, ML_BLACK, ML_XOR, ML_CHECKER} ML_Color;
char* ML_vram_adress();
void ML_clear_vram();
void ML_clear_screen();
void ML_display_vram();
void ML_set_contrast(unsigned char contrast);
unsigned char ML_get_contrast();
void ML_pixel(int x, int y, ML_Color color);
void ML_point(int x, int y, int width, ML_Color color);
ML_Color ML_pixel_test(int x, int y);
void ML_line(int x1, int y1, int x2, int y2, ML_Color color);
void ML_horizontal_line(int y, int x1, int x2, ML_Color color);
void ML_vertical_line(int x, int y1, int y2, ML_Color color);
void ML_rectangle(int x1, int y1, int x2, int y2, int border_width, ML_Color border_color, ML_Color fill_color);
void ML_polygon(const int *x, const int *y, int nb_vertices, ML_Color color);
void ML_filled_polygon(const int *x, const int *y, int nb_vertices, ML_Color color);
void ML_circle(int x, int y, int radius, ML_Color color);
void ML_filled_circle(int x, int y, int radius, ML_Color color);
void ML_ellipse(int x, int y, int radius1, int radius2, ML_Color color);
void ML_ellipse_in_rect(int x1, int y1, int x2, int y2, ML_Color color);
void ML_filled_ellipse(int x, int y, int radius1, int radius2, ML_Color color);
void ML_filled_ellipse_in_rect(int x, int y, int radius1, int radius2, ML_Color color);
void ML_horizontal_scroll(int scroll);
void ML_vertical_scroll(int scroll);
void ML_bmp_or(const unsigned char *bmp, int x, int y, int width, int height);
void ML_bmp_and(const unsigned char *bmp, int x, int y, int width, int height);
void ML_bmp_xor(const unsigned char *bmp, int x, int y, int width, int height);
void ML_bmp_or_cl(const unsigned char *bmp, int x, int y, int width, int height);
void ML_bmp_and_cl(const unsigned char *bmp, int x, int y, int width, int height);
void ML_bmp_xor_cl(const unsigned char *bmp, int x, int y, int width, int height);
void ML_bmp_8_or(const unsigned char *bmp, int x, int y);
void ML_bmp_8_and(const unsigned char *bmp, int x, int y);
void ML_bmp_8_xor(const unsigned char *bmp, int x, int y);
void ML_bmp_8_or_cl(const unsigned char *bmp, int x, int y);
void ML_bmp_8_and_cl(const unsigned char *bmp, int x, int y);
void ML_bmp_8_xor_cl(const unsigned char *bmp, int x, int y);
void ML_bmp_16_or(const unsigned short *bmp, int x, int y);
void ML_bmp_16_and(const unsigned short *bmp, int x, int y);
void ML_bmp_16_xor(const unsigned short *bmp, int x, int y);
void ML_bmp_16_or_cl(const unsigned short *bmp, int x, int y);
void ML_bmp_16_and_cl(const unsigned short *bmp, int x, int y);
void ML_bmp_16_xor_cl(const unsigned short *bmp, int x, int y);
#ifdef __cplusplus
}
#endif
#endif //MONOCHROMELIB
#include "time.h"
static int SysCallCode[] = {0xD201422B,0x60F20000,0x80010070}; // déclaration en global des adresses
static int (*SysCall)(int R4, int R5, int R6, int R7, int FNo ) = (void*)&SysCallCode; // et des registres
int RTC_getTicks(void)
{
return (*SysCall)(0, 0, 0, 0, 0x3B); // on déclare la fonction voulue selon son numéro (ici 0x3B)
}
void setFps(int fpsWish)
{
static unsigned int fps = 0, fps_count = 0; // "static" permet de garder les valeurs en mémoire entre les différents appels
do
{
fps = RTC_getTicks(); // on enregistre les ticks
Sleep(1); // permet d'économiser de la batterie
}
while(fps < fps_count+fpsWish); // tant que ceux-ci ne se sont pas suffisamment écoulés
fps_count = RTC_getTicks(); // on met à jour les dernières valeurs
}
#pragma once
int RTC_getTicks(void);
void setFps(int fpsWish);
///////////////////////////////////////////////////////////////////////////////
// Vectors.h
// =========
// 2D/3D/4D vectors
//
// AUTHOR: Song Ho Ahn (song.ahn@gmail.com)
// CREATED: 2007-02-14
// UPDATED: 2013-01-20
//
// Copyright (C) 2007-2013 Song Ho Ahn
///////////////////////////////////////////////////////////////////////////////
#pragma once
#include <math.h>
#include <mathf.h>
///////////////////////////////////////////////////////////////////////////////
// 2D vector
///////////////////////////////////////////////////////////////////////////////
struct Vector2
{
float x;
float y;
// ctors
Vector2() : x(0), y(0) {};
Vector2(float x, float y) : x(x), y(y) {};
// utils functions
void set(float x, float y);
float length() const; //
float distance(const Vector2& vec) const; // distance between two vectors
Vector2& normalize(); //
float dot(const Vector2& vec) const; // dot product
bool equal(const Vector2& vec, float e) const; // compare with epsilon
// operators
Vector2 operator-() const; // unary operator (negate)
Vector2 operator+(const Vector2& rhs) const; // add rhs
Vector2 operator-(const Vector2& rhs) const; // subtract rhs
Vector2& operator+=(const Vector2& rhs); // add rhs and update this object
Vector2& operator-=(const Vector2& rhs); // subtract rhs and update this object
Vector2 operator*(const float scale) const; // scale
Vector2 operator*(const Vector2& rhs) const; // multiply each element
Vector2& operator*=(const float scale); // scale and update this object
Vector2& operator*=(const Vector2& rhs); // multiply each element and update this object
Vector2 operator/(const float scale) const; // inverse scale
Vector2& operator/=(const float scale); // scale and update this object
bool operator==(const Vector2& rhs) const; // exact compare, no epsilon
bool operator!=(const Vector2& rhs) const; // exact compare, no epsilon
bool operator<(const Vector2& rhs) const; // comparison for sort
float operator[](int index) const; // subscript operator v[0], v[1]
float& operator[](int index); // subscript operator v[0], v[1]
friend Vector2 operator*(const float a, const Vector2 vec);
};
///////////////////////////////////////////////////////////////////////////////
// 3D vector
///////////////////////////////////////////////////////////////////////////////
struct Vector3
{
float x;
float y;
float z;
// ctors
Vector3() : x(0), y(0), z(0) {};
Vector3(float x, float y, float z) : x(x), y(y), z(z) {};
// utils functions
void set(float x, float y, float z);
float length() const; //
float distance(const Vector3& vec) const; // distance between two vectors
Vector3& normalize(); //
float dot(const Vector3& vec) const; // dot product
Vector3 cross(const Vector3& vec) const; // cross product
bool equal(const Vector3& vec, float e) const; // compare with epsilon
// operators
Vector3 operator-() const; // unary operator (negate)
Vector3 operator+(const Vector3& rhs) const; // add rhs
Vector3 operator-(const Vector3& rhs) const; // subtract rhs
Vector3& operator+=(const Vector3& rhs); // add rhs and update this object
Vector3& operator-=(const Vector3& rhs); // subtract rhs and update this object
Vector3 operator*(const float scale) const; // scale
Vector3 operator*(const Vector3& rhs) const; // multiplay each element
Vector3& operator*=(const float scale); // scale and update this object
Vector3& operator*=(const Vector3& rhs); // product each element and update this object
Vector3 operator/(const float scale) const; // inverse scale
Vector3& operator/=(const float scale); // scale and update this object
bool operator==(const Vector3& rhs) const; // exact compare, no epsilon
bool operator!=(const Vector3& rhs) const; // exact compare, no epsilon
bool operator<(const Vector3& rhs) const; // comparison for sort
float operator[](int index) const; // subscript operator v[0], v[1]
float& operator[](int index); // subscript operator v[0], v[1]
friend Vector3 operator*(const float a, const Vector3 vec);
};
///////////////////////////////////////////////////////////////////////////////
// 4D vector
///////////////////////////////////////////////////////////////////////////////
struct Vector4
{
float x;
float y;
float z;
float w;
// ctors
Vector4() : x(0), y(0), z(0), w(0) {};
Vector4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {};
// utils functions
void set(float x, float y, float z, float w);
float length() const; //
float distance(const Vector4& vec) const; // distance between two vectors
Vector4& normalize(); //
float dot(const Vector4& vec) const; // dot product
bool equal(const Vector4& vec, float e) const; // compare with epsilon
// operators
Vector4 operator-() const; // unary operator (negate)
Vector4 operator+(const Vector4& rhs) const; // add rhs
Vector4 operator-(const Vector4& rhs) const; // subtract rhs
Vector4& operator+=(const Vector4& rhs); // add rhs and update this object
Vector4& operator-=(const Vector4& rhs); // subtract rhs and update this object
Vector4 operator*(const float scale) const; // scale
Vector4 operator*(const Vector4& rhs) const; // multiply each element
Vector4& operator*=(const float scale); // scale and update this object
Vector4& operator*=(const Vector4& rhs); // multiply each element and update this object
Vector4 operator/(const float scale) const; // inverse scale
Vector4& operator/=(const float scale); // scale and update this object
bool operator==(const Vector4& rhs) const; // exact compare, no epsilon
bool operator!=(const Vector4& rhs) const; // exact compare, no epsilon
bool operator<(const Vector4& rhs) const; // comparison for sort
float operator[](int index) const; // subscript operator v[0], v[1]
float& operator[](int index); // subscript operator v[0], v[1]
friend Vector4 operator*(const float a, const Vector4 vec);
};
// fast math routines from Doom3 SDK
inline float invSqrt(float x)
{
float xhalf = 0.5f * x;
int i = *(int*)&x; // get bits for floating value
i = 0x5f3759df - (i>>1); // gives initial guess
x = *(float*)&i; // convert bits back to float
x = x * (1.5f - xhalf*x*x); // Newton step
return x;
}
///////////////////////////////////////////////////////////////////////////////
// inline functions for Vector2
///////////////////////////////////////////////////////////////////////////////
inline Vector2 Vector2::operator-() const {
return Vector2(-x, -y);
}
inline Vector2 Vector2::operator+(const Vector2& rhs) const {
return Vector2(x+rhs.x, y+rhs.y);
}
inline Vector2 Vector2::operator-(const Vector2& rhs) const {
return Vector2(x-rhs.x, y-rhs.y);
}
inline Vector2& Vector2::operator+=(const Vector2& rhs) {
x += rhs.x; y += rhs.y; return *this;
}
inline Vector2& Vector2::operator-=(const Vector2& rhs) {
x -= rhs.x; y -= rhs.y; return *this;
}
inline Vector2 Vector2::operator*(const float a) const {
return Vector2(x*a, y*a);
}
inline Vector2 Vector2::operator*(const Vector2& rhs) const {
return Vector2(x*rhs.x, y*rhs.y);
}
inline Vector2& Vector2::operator*=(const float a) {
x *= a; y *= a; return *this;
}
inline Vector2& Vector2::operator*=(const Vector2& rhs) {
x *= rhs.x; y *= rhs.y; return *this;
}
inline Vector2 Vector2::operator/(const float a) const {
return Vector2(x/a, y/a);
}
inline Vector2& Vector2::operator/=(const float a) {
x /= a; y /= a; return *this;
}
inline bool Vector2::operator==(const Vector2& rhs) const {
return (x == rhs.x) && (y == rhs.y);
}
inline bool Vector2::operator!=(const Vector2& rhs) const {
return (x != rhs.x) || (y != rhs.y);
}
inline bool Vector2::operator<(const Vector2& rhs) const {
if(x < rhs.x) return true;
if(x > rhs.x) return false;
if(y < rhs.y) return true;
if(y > rhs.y) return false;
return false;
}
inline float Vector2::operator[](int index) const {
return (&x)[index];
}
inline float& Vector2::operator[](int index) {
return (&x)[index];
}
inline void Vector2::set(float x, float y) {
this->x = x; this->y = y;
}
inline float Vector2::length() const {
return sqrtf(x*x + y*y);
}
inline float Vector2::distance(const Vector2& vec) const {
return sqrtf((vec.x-x)*(vec.x-x) + (vec.y-y)*(vec.y-y));
}
inline Vector2& Vector2::normalize() {
//@@const float EPSILON = 0.000001f;
float xxyy = x*x + y*y;
//@@if(xxyy < EPSILON)
//@@ return *this;
//float invLength = invSqrt(xxyy);
float invLength = 1.0f / sqrtf(xxyy);
x *= invLength;
y *= invLength;
return *this;
}
inline float Vector2::dot(const Vector2& rhs) const {
return (x*rhs.x + y*rhs.y);
}
inline bool Vector2::equal(const Vector2& rhs, float epsilon) const {
return fabs(x - rhs.x) < epsilon && fabs(y - rhs.y) < epsilon;
}
inline Vector2 operator*(const float a, const Vector2 vec) {
return Vector2(a*vec.x, a*vec.y);
}
// END OF VECTOR2 /////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// inline functions for Vector3
///////////////////////////////////////////////////////////////////////////////
inline Vector3 Vector3::operator-() const {
return Vector3(-x, -y, -z);
}
inline Vector3 Vector3::operator+(const Vector3& rhs) const {
return Vector3(x+rhs.x, y+rhs.y, z+rhs.z);
}
inline Vector3 Vector3::operator-(const Vector3& rhs) const {
return Vector3(x-rhs.x, y-rhs.y, z-rhs.z);
}
inline Vector3& Vector3::operator+=(const Vector3& rhs) {
x += rhs.x; y += rhs.y; z += rhs.z; return *this;
}
inline Vector3& Vector3::operator-=(const Vector3& rhs) {
x -= rhs.x; y -= rhs.y; z -= rhs.z; return *this;
}
inline Vector3 Vector3::operator*(const float a) const {
return Vector3(x*a, y*a, z*a);
}
inline Vector3 Vector3::operator*(const Vector3& rhs) const {
return Vector3(x*rhs.x, y*rhs.y, z*rhs.z);
}
inline Vector3& Vector3::operator*=(const float a) {
x *= a; y *= a; z *= a; return *this;
}
inline Vector3& Vector3::operator*=(const Vector3& rhs) {
x *= rhs.x; y *= rhs.y; z *= rhs.z; return *this;
}
inline Vector3 Vector3::operator/(const float a) const {
return Vector3(x/a, y/a, z/a);
}
inline Vector3& Vector3::operator/=(const float a) {
x /= a; y /= a; z /= a; return *this;
}
inline bool Vector3::operator==(const Vector3& rhs) const {
return (x == rhs.x) && (y == rhs.y) && (z == rhs.z);
}
inline bool Vector3::operator!=(const Vector3& rhs) const {
return (x != rhs.x) || (y != rhs.y) || (z != rhs.z);
}
inline bool Vector3::operator<(const Vector3& rhs) const {
if(x < rhs.x) return true;
if(x > rhs.x) return false;
if(y < rhs.y) return true;
if(y > rhs.y) return false;
if(z < rhs.z) return true;
if(z > rhs.z) return false;
return false;
}
inline float Vector3::operator[](int index) const {
return (&x)[index];
}
inline float& Vector3::operator[](int index) {
return (&x)[index];
}
inline void Vector3::set(float x, float y, float z) {
this->x = x; this->y = y; this->z = z;
}
inline float Vector3::length() const {
return sqrtf(x*x + y*y + z*z);
}
inline float Vector3::distance(const Vector3& vec) const {
return sqrtf((vec.x-x)*(vec.x-x) + (vec.y-y)*(vec.y-y) + (vec.z-z)*(vec.z-z));
}
inline Vector3& Vector3::normalize() {
//@@const float EPSILON = 0.000001f;
float xxyyzz = x*x + y*y + z*z;
//@@if(xxyyzz < EPSILON)
//@@ return *this; // do nothing if it is ~zero vector
//float invLength = invSqrt(xxyyzz);
float invLength = 1.0f / sqrtf(xxyyzz);
x *= invLength;
y *= invLength;
z *= invLength;
return *this;
}
inline float Vector3::dot(const Vector3& rhs) const {
return (x*rhs.x + y*rhs.y + z*rhs.z);
}
inline Vector3 Vector3::cross(const Vector3& rhs) const {
return Vector3(y*rhs.z - z*rhs.y, z*rhs.x - x*rhs.z, x*rhs.y - y*rhs.x);
}
inline bool Vector3::equal(const Vector3& rhs, float epsilon) const {
return fabs(x - rhs.x) < epsilon && fabs(y - rhs.y) < epsilon && fabs(z - rhs.z) < epsilon;
}
inline Vector3 operator*(const float a, const Vector3 vec) {
return Vector3(a*vec.x, a*vec.y, a*vec.z);
}
// END OF VECTOR3 /////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// inline functions for Vector4
///////////////////////////////////////////////////////////////////////////////
inline Vector4 Vector4::operator-() const {
return Vector4(-x, -y, -z, -w);
}
inline Vector4 Vector4::operator+(const Vector4& rhs) const {
return Vector4(x+rhs.x, y+rhs.y, z+rhs.z, w+rhs.w);
}
inline Vector4 Vector4::operator-(const Vector4& rhs) const {
return Vector4(x-rhs.x, y-rhs.y, z-rhs.z, w-rhs.w);
}
inline Vector4& Vector4::operator+=(const Vector4& rhs) {
x += rhs.x; y += rhs.y; z += rhs.z; w += rhs.w; return *this;
}
inline Vector4& Vector4::operator-=(const Vector4& rhs) {
x -= rhs.x; y -= rhs.y; z -= rhs.z; w -= rhs.w; return *this;
}
inline Vector4 Vector4::operator*(const float a) const {
return Vector4(x*a, y*a, z*a, w*a);
}
inline Vector4 Vector4::operator*(const Vector4& rhs) const {
return Vector4(x*rhs.x, y*rhs.y, z*rhs.z, w*rhs.w);
}
inline Vector4& Vector4::operator*=(const float a) {
x *= a; y *= a; z *= a; w *= a; return *this;
}
inline Vector4& Vector4::operator*=(const Vector4& rhs) {
x *= rhs.x; y *= rhs.y; z *= rhs.z; w *= rhs.w; return *this;
}
inline Vector4 Vector4::operator/(const float a) const {
return Vector4(x/a, y/a, z/a, w/a);
}
inline Vector4& Vector4::operator/=(const float a) {
x /= a; y /= a; z /= a; w /= a; return *this;
}
inline bool Vector4::operator==(const Vector4& rhs) const {
return (x == rhs.x) && (y == rhs.y) && (z == rhs.z) && (w == rhs.w);
}
inline bool Vector4::operator!=(const Vector4& rhs) const {
return (x != rhs.x) || (y != rhs.y) || (z != rhs.z) || (w != rhs.w);
}
inline bool Vector4::operator<(const Vector4& rhs) const {
if(x < rhs.x) return true;
if(x > rhs.x) return false;
if(y < rhs.y) return true;
if(y > rhs.y) return false;
if(z < rhs.z) return true;
if(z > rhs.z) return false;
if(w < rhs.w) return true;
if(w > rhs.w) return false;
return false;
}
inline float Vector4::operator[](int index) const {
return (&x)[index];
}
inline float& Vector4::operator[](int index) {
return (&x)[index];
}
inline void Vector4::set(float x, float y, float z, float w) {
this->x = x; this->y = y; this->z = z; this->w = w;
}
inline float Vector4::length() const {
return sqrtf(x*x + y*y + z*z + w*w);
}
inline float Vector4::distance(const Vector4& vec) const {
return sqrtf((vec.x-x)*(vec.x-x) + (vec.y-y)*(vec.y-y) + (vec.z-z)*(vec.z-z) + (vec.w-w)*(vec.w-w));
}
inline Vector4& Vector4::normalize() {
//NOTE: leave w-component untouched
//@@const float EPSILON = 0.000001f;
float xxyyzz = x*x + y*y + z*z;
//@@if(xxyyzz < EPSILON)
//@@ return *this; // do nothing if it is zero vector
//float invLength = invSqrt(xxyyzz);
float invLength = 1.0f / sqrtf(xxyyzz);
x *= invLength;
y *= invLength;
z *= invLength;
return *this;
}
inline float Vector4::dot(const Vector4& rhs) const {
return (x*rhs.x + y*rhs.y + z*rhs.z + w*rhs.w);
}
inline bool Vector4::equal(const Vector4& rhs, float epsilon) const {
return fabs(x - rhs.x) < epsilon && fabs(y - rhs.y) < epsilon &&
fabs(z - rhs.z) < epsilon && fabs(w - rhs.w) < epsilon;
}
inline Vector4 operator*(const float a, const Vector4 vec) {
return Vector4(a*vec.x, a*vec.y, a*vec.z, a*vec.w);
}
// END OF VECTOR4 /////////////////////////////////////////////////////////////
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment