CfgUSBLoader/lib/grrlib/GRRLIB/GRRLIB_3D.c
2015-01-17 10:11:08 +00:00

755 lines
26 KiB
C

/*------------------------------------------------------------------------------
Copyright (c) 2010 The GRRLIB Team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
------------------------------------------------------------------------------*/
#include <math.h>
#include <grrlib.h>
// User should not directly modify these
Mtx _GRR_view; // Should be static as soon as all light functions needing this var will be in this file ;)
static guVector _GRR_cam = {0.0F, 0.0F, 0.0F},
_GRR_up = {0.0F, 1.0F, 0.0F},
_GRR_look = {0.0F, 0.0F, -100.0F};
static guVector _GRRaxisx = (guVector){1, 0, 0}; // DO NOT MODIFY!!!
static guVector _GRRaxisy = (guVector){0, 1, 0}; // Even at runtime
static guVector _GRRaxisz = (guVector){0, 0, 1}; // NOT ever!
static Mtx _ObjTransformationMtx;
/**
* Set the background parameter when screen is cleared.
* @param r Red component.
* @param g Green component.
* @param b Blue component.
* @param a Alpha component.
*/
void GRRLIB_SetBackgroundColour(u8 r, u8 g, u8 b, u8 a) {
GX_SetCopyClear((GXColor){ r, g, b, a }, GX_MAX_Z24);
}
/**
* Set the camera parameter (contributed my chris_c aka DaShAmAn).
* @param posx x position of the camera.
* @param posy y position of the camera.
* @param posz z position of the camera.
* @param upx Alpha component.
* @param upy Alpha component.
* @param upz Alpha component.
* @param lookx x up position of the camera.
* @param looky y up position of the camera.
* @param lookz z up position of the camera.
*/
void GRRLIB_Camera3dSettings(f32 posx, f32 posy, f32 posz,
f32 upx, f32 upy, f32 upz,
f32 lookx, f32 looky, f32 lookz) {
_GRR_cam.x=posx;
_GRR_cam.y=posy;
_GRR_cam.z=posz;
_GRR_up.x=upx;
_GRR_up.y=upy;
_GRR_up.z=upz;
_GRR_look.x=lookx;
_GRR_look.y=looky;
_GRR_look.z=lookz;
}
/**
* Set up the position matrix (contributed by chris_c aka DaShAmAn).
* @param minDist Minimal distance for the camera.
* @param maxDist Maximal distance for the camera.
* @param fov Field of view for the camera.
* @param texturemode False, GX won't need texture coordinate, True, GX will need texture coordinate.
* @param normalmode False, GX won't need normal coordinate, True, GX will need normal coordinate.
*/
void GRRLIB_3dMode(f32 minDist, f32 maxDist, f32 fov, bool texturemode, bool normalmode) {
Mtx m;
guLookAt(_GRR_view, &_GRR_cam, &_GRR_up, &_GRR_look);
guPerspective(m, fov, (f32)rmode->fbWidth/rmode->efbHeight, minDist, maxDist);
GX_LoadProjectionMtx(m, GX_PERSPECTIVE);
GX_SetZMode (GX_TRUE, GX_LEQUAL, GX_TRUE);
GX_SetCullMode(GX_CULL_NONE);
GX_ClearVtxDesc();
GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
if(normalmode) GX_SetVtxDesc(GX_VA_NRM, GX_DIRECT);
GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT);
if(texturemode) GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
if(normalmode) GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
if(texturemode) GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
if(texturemode) GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE);
else GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
}
/**
* Go back to 2D mode (contributed by chris_c aka DaShAmAn).
*/
void GRRLIB_2dMode() {
Mtx view, m;
GX_SetZMode(GX_FALSE, GX_LEQUAL, GX_TRUE);
GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
guOrtho(m, 0, rmode->efbHeight, 0, rmode->fbWidth, 0, 1000.0f);
GX_LoadProjectionMtx(m, GX_ORTHOGRAPHIC);
guMtxIdentity(view);
guMtxTransApply(view, view, 0, 0, -100.0F);
GX_LoadPosMtxImm(view, GX_PNMTX0);
GX_ClearVtxDesc();
GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT);
GX_SetVtxDesc(GX_VA_TEX0, GX_NONE);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GX_SetNumTexGens(1); // One texture exists
GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
GX_SetNumTevStages(1);
GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR);
GX_SetNumChans(1);
GX_SetChanCtrl(GX_COLOR0A0, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE);
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
GRRLIB_Settings.lights = 0;
}
/**
* Init the object matrix to draw object.
*/
void GRRLIB_ObjectViewBegin(void) {
guMtxIdentity(_ObjTransformationMtx);
}
/**
* Scale the object matrix to draw object.
* @param scalx x scale of the object.
* @param scaly y scale of the object.
* @param scalz z scale of the object.
*/
void GRRLIB_ObjectViewScale(f32 scalx, f32 scaly, f32 scalz) {
Mtx m;
guMtxIdentity(m);
guMtxScaleApply(m, m, scalx, scaly, scalz);
guMtxConcat(m, _ObjTransformationMtx, _ObjTransformationMtx);
}
/**
* Rotate the object matrix to draw object .
* @param angx x rotation angle of the object.
* @param angy y rotation angle of the object.
* @param angz z rotation angle of the object.
*/
void GRRLIB_ObjectViewRotate(f32 angx, f32 angy, f32 angz) {
Mtx m, rx,ry,rz;
guMtxIdentity(m);
guMtxRotAxisDeg(rx, &_GRRaxisx, angx);
guMtxRotAxisDeg(ry, &_GRRaxisy, angy);
guMtxRotAxisDeg(rz, &_GRRaxisz, angz);
guMtxConcat(ry, rx, m);
guMtxConcat(m, rz, m);
guMtxConcat(m, _ObjTransformationMtx, _ObjTransformationMtx);
}
/**
* Translate the object matrix to draw object.
* @param posx x position of the object.
* @param posy y position of the object.
* @param posz z position of the object.
*/
void GRRLIB_ObjectViewTrans(f32 posx, f32 posy, f32 posz) {
Mtx m;
guMtxIdentity(m);
guMtxTransApply(m, m, posx, posy, posz);
guMtxConcat(m, _ObjTransformationMtx, _ObjTransformationMtx);
}
/**
* Concat the object and the view matrix and calculate the inverse normal matrix.
*/
void GRRLIB_ObjectViewEnd(void) {
Mtx mv, mvi;
guMtxConcat(_GRR_view, _ObjTransformationMtx, mv);
GX_LoadPosMtxImm(mv, GX_PNMTX0);
guMtxInverse(mv, mvi);
guMtxTranspose(mvi, mv);
GX_LoadNrmMtxImm(mv, GX_PNMTX0);
}
/**
* Set the view matrix to draw object (in this order scale, rotate AND trans).
* @param posx x position of the object.
* @param posy y position of the object.
* @param posz z position of the object.
* @param angx x rotation angle of the object.
* @param angy y rotation angle of the object.
* @param angz z rotation angle of the object.
* @param scalx x scale of the object.
* @param scaly y scale of the object.
* @param scalz z scale of the object.
*/
void GRRLIB_ObjectView(f32 posx, f32 posy, f32 posz, f32 angx, f32 angy, f32 angz, f32 scalx, f32 scaly, f32 scalz) {
Mtx ObjTransformationMtx;
Mtx m, rx,ry,rz;
Mtx mv, mvi;
guMtxIdentity(ObjTransformationMtx);
if((scalx !=1.0f) || (scaly !=1.0f) || (scalz !=1.0f)) {
guMtxIdentity(m);
guMtxScaleApply(m, m, scalx, scaly, scalz);
guMtxConcat(m, ObjTransformationMtx, ObjTransformationMtx);
}
if((angx !=0.0f) || (angy !=0.0f) || (angz !=0.0f)) {
guMtxIdentity(m);
guMtxRotAxisDeg(rx, &_GRRaxisx, angx);
guMtxRotAxisDeg(ry, &_GRRaxisy, angy);
guMtxRotAxisDeg(rz, &_GRRaxisz, angz);
guMtxConcat(ry, rx, m);
guMtxConcat(m, rz, m);
guMtxConcat(m, ObjTransformationMtx, ObjTransformationMtx);
}
if((posx !=0.0f) || (posy !=0.0f) || (posz !=0.0f)) {
guMtxIdentity(m);
guMtxTransApply(m, m, posx, posy, posz);
guMtxConcat(m, ObjTransformationMtx, ObjTransformationMtx);
}
guMtxConcat(_GRR_view, ObjTransformationMtx, mv);
GX_LoadPosMtxImm(mv, GX_PNMTX0);
guMtxInverse(mv, mvi);
guMtxTranspose(mvi, mv);
GX_LoadNrmMtxImm(mv, GX_PNMTX0);
}
/**
* Set the view matrix to draw object (in this order scale, trans AND rotate).
* @param posx x position of the object.
* @param posy y position of the object.
* @param posz z position of the object.
* @param angx x rotation angle of the object.
* @param angy y rotation angle of the object.
* @param angz z rotation angle of the object.
* @param scalx x scale of the object.
* @param scaly y scale of the object.
* @param scalz z scale of the object.
*/
void GRRLIB_ObjectViewInv(f32 posx, f32 posy, f32 posz, f32 angx, f32 angy, f32 angz, f32 scalx, f32 scaly, f32 scalz) {
Mtx ObjTransformationMtx;
Mtx m, rx,ry,rz;
Mtx mv, mvi;
guMtxIdentity(ObjTransformationMtx);
if((scalx !=1.0f) || (scaly !=1.0f) || (scalz !=1.0f)) {
guMtxIdentity(m);
guMtxScaleApply(m, m, scalx, scaly, scalz);
guMtxConcat(m, ObjTransformationMtx, ObjTransformationMtx);
}
if((posx !=0.0f) || (posy !=0.0f) || (posz !=0.0f)) {
guMtxIdentity(m);
guMtxTransApply(m, m, posx, posy, posz);
guMtxConcat(m, ObjTransformationMtx, ObjTransformationMtx);
}
if((angx !=0.0f) || (angy !=0.0f) || (angz !=0.0f)) {
guMtxIdentity(m);
guMtxRotAxisDeg(rx, &_GRRaxisx, angx);
guMtxRotAxisDeg(ry, &_GRRaxisy, angy);
guMtxRotAxisDeg(rz, &_GRRaxisz, angz);
guMtxConcat(ry, rx, m);
guMtxConcat(m, rz, m);
guMtxConcat(m, ObjTransformationMtx, ObjTransformationMtx);
}
guMtxConcat(_GRR_view, ObjTransformationMtx, mv);
GX_LoadPosMtxImm(mv, GX_PNMTX0);
guMtxInverse(mv, mvi);
guMtxTranspose(mvi, mv);
GX_LoadNrmMtxImm(mv, GX_PNMTX0);
}
/**
* Set the texture to an object (contributed by chris_c aka DaShAmAn).
* @param tex Pointer to an image texture (GRRLIB_texImg format).
* @param rep Texture Repeat Mode, True will repeat it, False won't.
*/
void GRRLIB_SetTexture(GRRLIB_texImg *tex, bool rep) {
GXTexObj texObj;
if (rep) {
GX_InitTexObj(&texObj, tex->data, tex->w, tex->h, GX_TF_RGBA8, GX_REPEAT, GX_REPEAT, GX_FALSE);
}
else {
GX_InitTexObj(&texObj, tex->data, tex->w, tex->h, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
}
if (GRRLIB_Settings.antialias == false) {
GX_InitTexObjLOD(&texObj, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, 0, 0, GX_ANISO_1);
GX_SetCopyFilter(GX_FALSE, rmode->sample_pattern, GX_FALSE, rmode->vfilter);
}
else {
GX_SetCopyFilter(rmode->aa, rmode->sample_pattern, GX_TRUE, rmode->vfilter);
}
GX_LoadTexObj(&texObj, GX_TEXMAP0);
GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
}
/**
* Draw a torus (with normal).
* @param r Radius of the ring.
* @param R Radius of the torus.
* @param nsides Number of faces per ring.
* @param rings Number of rings.
* @param filled Wired or not.
* @param col Color of the torus.
*/
void GRRLIB_DrawTorus(f32 r, f32 R, int nsides, int rings, bool filled, u32 col) {
int i, j;
f32 theta, phi, theta1;
f32 cosTheta, sinTheta;
f32 cosTheta1, sinTheta1;
f32 ringDelta, sideDelta;
f32 cosPhi, sinPhi, dist;
ringDelta = 2.0 * M_PI / rings;
sideDelta = 2.0 * M_PI / nsides;
theta = 0.0;
cosTheta = 1.0;
sinTheta = 0.0;
for (i = rings - 1; i >= 0; i--) {
theta1 = theta + ringDelta;
cosTheta1 = cos(theta1);
sinTheta1 = sin(theta1);
if(filled) GX_Begin(GX_TRIANGLESTRIP, GX_VTXFMT0, 2*(nsides+1));
else GX_Begin(GX_LINESTRIP, GX_VTXFMT0, 2*(nsides+1));
phi = 0.0;
for (j = nsides; j >= 0; j--) {
phi += sideDelta;
cosPhi = cos(phi);
sinPhi = sin(phi);
dist = R + r * cosPhi;
GX_Position3f32(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
GX_Normal3f32(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
GX_Color1u32(col);
GX_Position3f32(cosTheta * dist, -sinTheta * dist, r * sinPhi);
GX_Normal3f32(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
GX_Color1u32(col);
}
GX_End();
theta = theta1;
cosTheta = cosTheta1;
sinTheta = sinTheta1;
}
}
/**
* Draw a sphere (with normal).
* @param r Radius of the sphere.
* @param lats Number of lattitudes.
* @param longs Number of longitutes.
* @param filled Wired or not.
* @param col Color of the sphere.
*/
void GRRLIB_DrawSphere(f32 r, int lats, int longs, bool filled, u32 col) {
int i, j;
f32 lat0, z0, zr0,
lat1, z1, zr1,
lng, x, y;
for(i = 0; i <= lats; i++) {
lat0 = M_PI * (-0.5F + (f32) (i - 1) / lats);
z0 = sin(lat0);
zr0 = cos(lat0);
lat1 = M_PI * (-0.5F + (f32) i / lats);
z1 = sin(lat1);
zr1 = cos(lat1);
if(filled) GX_Begin(GX_TRIANGLESTRIP, GX_VTXFMT0, 2*(longs+1));
else GX_Begin(GX_LINESTRIP, GX_VTXFMT0, 2*(longs+1));
for(j = 0; j <= longs; j++) {
lng = 2 * M_PI * (f32) (j - 1) / longs;
x = cos(lng);
y = sin(lng);
GX_Position3f32(x * zr0 * r, y * zr0 * r, z0 * r);
GX_Normal3f32(x * zr0 * r, y * zr0 * r, z0 * r);
GX_Color1u32(col);
GX_Position3f32(x * zr1 * r, y * zr1 * r, z1 * r);
GX_Normal3f32(x * zr1 * r, y * zr1 * r, z1 * r);
GX_Color1u32(col);
}
GX_End();
}
}
/**
* Draw a cube (with normal).
* @param size Size of the cube edge.
* @param filled Wired or not.
* @param col Color of the cube.
*/
void GRRLIB_DrawCube(f32 size, bool filled, u32 col) {
static f32 n[6][3] =
{
{-1.0, 0.0, 0.0},
{0.0, 1.0, 0.0},
{1.0, 0.0, 0.0},
{0.0, -1.0, 0.0},
{0.0, 0.0, 1.0},
{0.0, 0.0, -1.0}
};
static int faces[6][4] =
{
{0, 1, 2, 3},
{3, 2, 6, 7},
{7, 6, 5, 4},
{4, 5, 1, 0},
{5, 6, 2, 1},
{7, 4, 0, 3}
};
f32 v[8][3];
int i;
v[0][0] = v[1][0] = v[2][0] = v[3][0] = -size / 2;
v[4][0] = v[5][0] = v[6][0] = v[7][0] = size / 2;
v[0][1] = v[1][1] = v[4][1] = v[5][1] = -size / 2;
v[2][1] = v[3][1] = v[6][1] = v[7][1] = size / 2;
v[0][2] = v[3][2] = v[4][2] = v[7][2] = -size / 2;
v[1][2] = v[2][2] = v[5][2] = v[6][2] = size / 2;
for (i = 5; i >= 0; i--) {
if(filled) GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
else GX_Begin(GX_LINESTRIP, GX_VTXFMT0, 5);
GX_Position3f32(v[faces[i][0]][0], v[faces[i][0]][1], v[faces[i][0]][2] );
GX_Normal3f32(n[i][0], n[i][1], n[i][2]);
GX_Color1u32(col);
GX_Position3f32(v[faces[i][1]][0], v[faces[i][1]][1], v[faces[i][1]][2]);
GX_Normal3f32(n[i][0], n[i][1], n[i][2]);
GX_Color1u32(col);
GX_Position3f32(v[faces[i][2]][0], v[faces[i][2]][1], v[faces[i][2]][2]);
GX_Normal3f32(n[i][0], n[i][1], n[i][2]);
GX_Color1u32(col);
GX_Position3f32(v[faces[i][3]][0], v[faces[i][3]][1], v[faces[i][3]][2]);
GX_Normal3f32(n[i][0], n[i][1], n[i][2]);
GX_Color1u32(col);
if(!filled) {
GX_Position3f32(v[faces[i][0]][0], v[faces[i][0]][1], v[faces[i][0]][2]);
GX_Normal3f32(n[i][0], n[i][1], n[i][2]);
GX_Color1u32(col);
}
GX_End();
}
}
/**
* Draw a cylinder (with normal).
* @param r Radius of the cylinder.
* @param h High of the cylinder.
* @param d Dencity of slice.
* @param filled Wired or not.
* @param col Color of the cylinder.
*/
void GRRLIB_DrawCylinder(f32 r, f32 h, int d, bool filled, u32 col) {
int i;
f32 dx, dy;
if(filled) GX_Begin(GX_TRIANGLESTRIP, GX_VTXFMT0, 2 * (d+1));
else GX_Begin(GX_LINESTRIP, GX_VTXFMT0, 2 * (d+1));
for(i = 0 ; i <= d ; i++) {
dx = cosf( M_PI * 2.0f * i / d );
dy = sinf( M_PI * 2.0f * i / d );
GX_Position3f32( r * dx, -0.5f * h, r * dy );
GX_Normal3f32( dx, 0.0f, dy );
GX_Color1u32(col);
GX_Position3f32( r * dx, 0.5f * h, r * dy );
GX_Normal3f32( dx, 0.0f, dy );
GX_Color1u32(col);
}
GX_End();
if(filled) GX_Begin(GX_TRIANGLEFAN, GX_VTXFMT0, d+2);
else GX_Begin(GX_LINESTRIP, GX_VTXFMT0, d+2);
GX_Position3f32(0.0f, -0.5f * h, 0.0f);
GX_Normal3f32(0.0f, -1.0f, 0.0f);
GX_Color1u32(col);
for(i = 0 ; i <= d ; i++) {
GX_Position3f32( r * cosf( M_PI * 2.0f * i / d ), -0.5f * h, r * sinf( M_PI * 2.0f * i / d ) );
GX_Normal3f32(0.0f, -1.0f, 0.0f);
GX_Color1u32(col);
}
GX_End();
if(filled) GX_Begin(GX_TRIANGLEFAN, GX_VTXFMT0, d+2);
else GX_Begin(GX_LINESTRIP, GX_VTXFMT0, d+2);
GX_Position3f32(0.0f, 0.5f * h, 0.0f);
GX_Normal3f32(0.0f, 1.0f, 0.0f);
GX_Color1u32(col);
for(i = 0 ; i <= d ; i++) {
GX_Position3f32( r * cosf( M_PI * 2.0f * i / d ), 0.5f * h, r * sinf( M_PI * 2.0f * i / d ) );
GX_Normal3f32(0.0f, 1.0f, 0.0f);
GX_Color1u32(col);
}
GX_End();
}
/**
* Draw a cone (with normal).
* @param r Radius of the cone.
* @param h High of the cone.
* @param d Dencity of slice.
* @param filled Wired or not.
* @param col Color of the cone.
*/
void GRRLIB_DrawCone(f32 r, f32 h, int d, bool filled, u32 col) {
int i;
f32 dx, dy;
if(filled) GX_Begin(GX_TRIANGLESTRIP, GX_VTXFMT0, 2 * (d+1));
else GX_Begin(GX_LINESTRIP, GX_VTXFMT0, 2 * (d+1));
for(i = 0 ; i <= d ; i++) {
dx = cosf( M_PI * 2.0f * i / d );
dy = sinf( M_PI * 2.0f * i / d );
GX_Position3f32( 0, -0.5f * h,0);
GX_Normal3f32( dx, 0.0f, dy );
GX_Color1u32(col);
GX_Position3f32( r * dx, 0.5f * h, r * dy );
GX_Normal3f32( dx, 0.0f, dy );
GX_Color1u32(col);
}
GX_End();
if(filled) GX_Begin(GX_TRIANGLEFAN, GX_VTXFMT0, d+2);
else GX_Begin(GX_LINESTRIP, GX_VTXFMT0, d+2);
GX_Position3f32(0.0f, 0.5f * h, 0.0f);
GX_Normal3f32(0.0f, 1.0f, 0.0f);
GX_Color1u32(col);
for(i = 0 ; i <= d ; i++) {
GX_Position3f32( r * cosf( M_PI * 2.0f * i / d ), 0.5f * h, r * sinf( M_PI * 2.0f * i / d ) );
GX_Normal3f32(0.0f, 1.0f, 0.0f);
GX_Color1u32(col);
}
GX_End();
}
/**
* Draw a Tesselated pannel (with normal).
* @param w Width of the panel.
* @param wstep Size of width slices.
* @param h Height of the pannel.
* @param hstep Size the de height slices.
* @param filled Wired or not.
* @param col Color in RGBA format.
*/
void GRRLIB_DrawTessPanel(f32 w, f32 wstep, f32 h, f32 hstep, bool filled, u32 col) {
f32 x,y,tmpx, tmpy;
int tmp;
tmpy = h/2.0f;
tmpx = w/2.0f;
tmp = ((w/wstep)*2)+2;
for ( y = -tmpy ; y <= tmpy ; y+=hstep )
{
if(filled) GX_Begin(GX_TRIANGLESTRIP, GX_VTXFMT0, tmp);
else GX_Begin(GX_LINESTRIP, GX_VTXFMT0, tmp);
for ( x = -tmpx ; x <= tmpx ; x+=wstep )
{
GX_Position3f32( x, y, 0.0f );
GX_Normal3f32( 0.0f, 0.0f, 1.0f);
GX_Color1u32(col);
GX_Position3f32( x, y+hstep, 0.0f );
GX_Normal3f32( 0.0f, 0.0f, 1.0f);
GX_Color1u32(col);
}
GX_End();
}
}
/**
* Set ambient color.
* When no diffuse ligth is shinig on a object, the color is equal to ambient color.
* @param ambientcolor Ambient color in RGBA format.
*/
void GRRLIB_SetLightAmbient(u32 ambientcolor) {
GX_SetChanAmbColor(GX_COLOR0A0, (GXColor) { R(ambientcolor), G(ambientcolor), B(ambientcolor), 0xFF});
}
/**
* Set diffuse light parameters.
* @param num Number of the light. It's a number from 0 to 7.
* @param pos Position of the diffuse light (x/y/z).
* @param distattn Distance attenuation.
* @param brightness Brightness of the light. The value should be between 0 and 1.
* @param lightcolor Color of the light in RGBA format.
*/
void GRRLIB_SetLightDiff(u8 num, guVector pos, f32 distattn, f32 brightness, u32 lightcolor) {
GXLightObj MyLight;
guVector lpos = {pos.x, pos.y, pos.z};
GRRLIB_Settings.lights |= (1<<num);
guVecMultiply(_GRR_view, &lpos, &lpos);
GX_InitLightPos(&MyLight, lpos.x, lpos.y, lpos.z);
GX_InitLightColor(&MyLight, (GXColor) { R(lightcolor), G(lightcolor), B(lightcolor), 0xFF });
GX_InitLightSpot(&MyLight, 0.0f, GX_SP_OFF);
GX_InitLightDistAttn(&MyLight, distattn, brightness, GX_DA_MEDIUM); // DistAttn = 20.0 & Brightness=1.0f (full)
GX_LoadLightObj(&MyLight, (1<<num));
// Turn light ON
GX_SetNumChans(1);
GX_SetChanCtrl(GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_VTX, GRRLIB_Settings.lights, GX_DF_CLAMP, GX_AF_SPOT);
}
/**
* Set specular light parameters.
* @param num Number of the light. It's a number from 0 to 7.
* @param dir Direction of the specular ray (x/y/z).
* @param shy Shyniness of the specular. ( between 4 and 254)
* @param lightcolor Color of the light in RGBA format.
* @param speccolor Specular color in RGBA format..
*/
void GRRLIB_SetLightSpec(u8 num, guVector dir, f32 shy, u32 lightcolor, u32 speccolor) {
Mtx mr,mv;
GXLightObj MyLight;
guVector ldir = {dir.x, dir.y, dir.z};
GRRLIB_Settings.lights |= (1<<num);
guMtxInverse(_GRR_view,mr);
guMtxTranspose(mr,mv);
guVecMultiplySR(mv, &ldir,&ldir);
GX_InitSpecularDirv(&MyLight, &ldir);
GX_InitLightShininess(&MyLight, shy); // between 4 and 255 !!!
GX_InitLightColor(&MyLight, (GXColor) { R(lightcolor), G(lightcolor), B(lightcolor), 0xFF });
GX_LoadLightObj(&MyLight, (1<<num));
/////////////////////// Turn light ON ////////////////////////////////////////////////
GX_SetNumChans(2); // use two color channels
GX_SetChanCtrl(GX_COLOR0, GX_ENABLE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT0, GX_DF_CLAMP, GX_AF_NONE);
GX_SetChanCtrl(GX_COLOR1, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0, GX_DF_NONE, GX_AF_SPEC);
GX_SetChanCtrl(GX_ALPHA0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHTNULL, GX_DF_NONE, GX_AF_NONE);
GX_SetChanCtrl(GX_ALPHA1, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHTNULL, GX_DF_NONE, GX_AF_NONE);
GX_SetNumTevStages(2);
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORDNULL, GX_TEXMAP_NULL, GX_COLOR0A0 );
GX_SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORDNULL, GX_TEXMAP_NULL, GX_COLOR1A1 );
GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
GX_SetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV );
GX_SetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_RASC, GX_CC_ONE, GX_CC_CPREV );
/////////////////////// Define Material and Ambiant color and draw object /////////////////////////////////////
GX_SetChanAmbColor(GX_COLOR1, (GXColor){0x00,0x00,0x00,0xFF}); // specualr ambient forced to black
GX_SetChanMatColor(GX_COLOR1, (GXColor) { R(speccolor), G(speccolor), B(speccolor), 0xFF }); // couleur du reflet specular
}
/**
* Set Spot light parameters.
* @param num Number of the light. It's a number from 0 to 7.
* @param pos Position of the spot light (x/y/z).
* @param lookat Where spot light look at (x/y/z).
* @param angAttn0 cone attenuation factor 0.
* @param angAttn1 cone attenuation factor 1.
* @param angAttn2 cone attenuation factor 2.
* @param distAttn0 Distance attenuation factor 0.
* @param distAttn1 Distance attenuation factor 1.
* @param distAttn2 Distance attenuation factor 2.
* @param lightcolor Color of the light in RGBA format.
*/
void GRRLIB_SetLightSpot(u8 num, guVector pos, guVector lookat, f32 angAttn0, f32 angAttn1, f32 angAttn2, f32 distAttn0, f32 distAttn1, f32 distAttn2, u32 lightcolor) {
GXLightObj lobj;
guVector lpos = (guVector){ pos.x, pos.y, pos.z };
guVector ldir = (guVector){ lookat.x-pos.x, lookat.y-pos.y, lookat.z-pos.z };
guVecNormalize(&ldir);
GRRLIB_Settings.lights |= (1<<num);
guVecMultiplySR(_GRR_view, &ldir,&ldir);
guVecMultiply(_GRR_view, &lpos, &lpos);
GX_InitLightDirv(&lobj, &ldir);
GX_InitLightPosv(&lobj, &lpos);
GX_InitLightColor(&lobj, (GXColor) { R(lightcolor), G(lightcolor), B(lightcolor), 0xFF });
//this is just for code readers, wanting to know how to use direct cut off
//GX_InitLightSpot(&lobj, 0<angle<90, GX_SP_FLAT);
GX_InitLightAttn(&lobj, angAttn0, angAttn1, angAttn2, distAttn0, distAttn1, distAttn2);
GX_LoadLightObj(&lobj, (1<<num));
// Turn light ON
GX_SetNumChans(1);
GX_SetChanCtrl(GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_VTX, GRRLIB_Settings.lights, GX_DF_CLAMP, GX_AF_SPOT);
}
/**
* Set all lights off, like at init.
*/
void GRRLIB_SetLightOff(void) {
GX_SetNumTevStages(1);
GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR);
GX_SetNumChans(1);
GX_SetChanCtrl(GX_COLOR0A0, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE);
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
GRRLIB_Settings.lights = 0;
}