From 7d4e4c0b34a613dd3c0220475ae4e448197522c1 Mon Sep 17 00:00:00 2001 From: Treeki Date: Sat, 12 Mar 2011 23:17:12 +0100 Subject: initial commit. now I can start playing with stuff! --- 3dlib/treeki3d.cpp | 502 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 502 insertions(+) create mode 100644 3dlib/treeki3d.cpp (limited to '3dlib/treeki3d.cpp') diff --git a/3dlib/treeki3d.cpp b/3dlib/treeki3d.cpp new file mode 100644 index 0000000..3c72652 --- /dev/null +++ b/3dlib/treeki3d.cpp @@ -0,0 +1,502 @@ +/* Treeki's 3D Library for Wii */ + +#include "3dlib/treeki3d.h" + +#include +#include "rvl/PPCWGPipe.h" +#include "rvl/GXVert.h" + +namespace T3D { + +const GXColor Black = {0,0,0,255}; +const GXColor White = {255,255,255,255}; + +u32 HasBeenInited; + +RenderInfo *RenderQueue; +int RenderQueuePos; + +CameraInfo Camera; + +tmdl_material *LastMaterial; + +int tmdl_header_sizes[] = {0, 0, sizeof(tmdl_headerv2), sizeof(tmdl_header)}; + +bool Init(bool test) { + if (HasBeenInited == 'T3Df') + return test; + + HasBeenInited = 'T3Df'; + + OSReport("T3D Engine revision 3 -- created by Treeki\n"); + OSReport("Setting up the render queue for %d model(s).\n", OBJ_COUNT); + + RenderQueue = new RenderInfo[OBJ_COUNT]; + RenderQueuePos = 0; + + // Setup camera + Camera.projection = GX_PERSPECTIVE; + + GXRenderModeObj *rm = Hook_GetGXRenderModeObj(); + f32 aspect = (f32)rm->viWidth / (f32)rm->viHeight; + + OSReport("Dump of GXRenderModeObj settings:\n"); + OSReport("viTVmode => %d; fbWidth => %d; efbHeight => %d; xfbHeight => %d\n", rm->viTVmode, rm->fbWidth, rm->efbHeight, rm->xfbHeight); + OSReport("viXOrigin => %d; viYOrigin => %d; viWidth => %d; viHeight => %d\n", rm->viXOrigin, rm->viYOrigin, rm->viWidth, rm->viHeight); + OSReport("xFBmode => %d; field_rendering => %d; aa => %d\n", rm->xFBmode, rm->field_rendering, rm->aa); + + OSReport("Calculated VI aspect: %f\n", aspect); + + MTXPerspective(Camera.projection_matrix, 45, aspect, 0.1f, 2400.0f); + + Point3d camPos = {0,0,-150}; + Vec camUp = {0,1,0}; + Point3d target = {0,0,0}; + MTXLookAt(Camera.view_matrix, &camPos, &camUp, &target); + + return test; +} + +bool Model::bind(void *data, const char *mdlname) { + ARCHandle arc; + ARCFileInfo model_info; + tmdl_header *model = 0; + + OSReport("[T3D] Loading model %s\n", mdlname); + + // obtain the files from the arc + char model_name[64]; + snprintf(model_name, 64, "t3d/mdl_%s.tmdl", mdlname); + + if (!ARCInitHandle(data, &arc)) { + OSReport("[T3D] CANNOT LOAD ARC!!\n"); + OSReport("ARCInitHandle returned false\n"); + return false; + } + + if (ARCOpen(&arc, model_name, &model_info)) { + model = (tmdl_header*)ARCGetStartAddrInMem(&model_info); + ARCClose(&model_info); + } else { + OSReport("[T3D] CANNOT GET MODEL!!\n"); + OSReport("ARCOpen could not get %s\n", model_name); + return false; + } + + // bind it + if (model->version != 3 && model->version != 2) { + OSReport("[T3D] INVALID VERSION!!\n"); + OSReport("this revision of T3D expects a v2 or v3 model file, not %d\n", model->version); + return false; + } + + OSReport("Loading model version %d\n", model->version); + + // fix up every shape's GX arrays + for (int shape_id = 0; shape_id < model->shape_count; shape_id++) { + u32 shape_offset = *(u32*)((u32)model + tmdl_header_sizes[model->version] + (4*shape_id)); + tmdl_shape *shape = (tmdl_shape*)((u32)model + shape_offset); + + void *pos_arr = (void*)((u32)model + shape->pos_arr_offset); + void *nrm_arr = (void*)((u32)model + shape->nrm_arr_offset); + void *uv_arr = (void*)((u32)model + shape->uv_arr_offset); + + DCStoreRangeNoSync(pos_arr, shape->pos_arr_size); + DCStoreRangeNoSync(nrm_arr, shape->nrm_arr_size); + DCStoreRangeNoSync(uv_arr, shape->uv_arr_size); + } + + if (model->version == 2) { + ARCFileInfo texture_info; + char texture_name[64]; + snprintf(texture_name, 64, "t3d/tex_%s.tpl", mdlname); + + if (ARCOpen(&arc, texture_name, &texture_info)) { + this->texture_res = (TPLPalette*)ARCGetStartAddrInMem(&texture_info); + ARCClose(&texture_info); + } + + if (this->texture_res) { + TPLBind(this->texture_res); + } + } + + if (model->version >= 3) { + // now fix up every material + tmdl_material *mat = (tmdl_material*)((u32)model + sizeof(tmdl_header) + (4*model->shape_count)); + for (int mat_id = 0; mat_id < model->material_count; mat_id++) { + ARCFileInfo texture_info; + TPLPalette *texture = 0; + + if (ARCOpen(&arc, mat->texture_name, &texture_info)) { + texture = (TPLPalette*)ARCGetStartAddrInMem(&texture_info); + ARCClose(&texture_info); + } + + if (texture) { + TPLBind(texture); + TPLGetGXTexObjFromPalette(texture, &mat->texobj, 0); + GXInitTexObjWrapMode(&mat->texobj, GX_REPEAT, GX_REPEAT); + } else { + OSReport("[T3D] WARNING!! Texture %s was not found while loading model %s!\n", mat->texture_name, mdlname); + } + + mat++; + } + } + + // done! + this->model_res = model; + + return true; +} + +void Model::addToDrawList(Mtx mtx) { + if (RenderQueuePos >= OBJ_COUNT) { + OSReport("FATAL ERROR!!\n"); + OSReport("T3D object limit reached, render queue will overflow\n"); + return; + } + + RenderInfo *info = &RenderQueue[RenderQueuePos++]; + MTXCopy(mtx, info->matrix); + info->model = this; +} + +void Model::draw(RenderInfo *info) { + Mtx matrix, inv_matrix; + MTXCopy(Camera.view_matrix, matrix); + MTXConcat(info->matrix, matrix, matrix); + + GXLoadPosMtxImm(matrix, GX_PNMTX0); + + MTXInverse(matrix, inv_matrix); + GXLoadNrmMtxImm(inv_matrix, GX_PNMTX0); + + for (int i = 0; i < this->model_res->shape_count; i++) + this->drawShape(info, i); +} + +void Model::drawShape(RenderInfo *info, int shape_id) { + u32 shape_offset = *(u32*)((u32)this->model_res + tmdl_header_sizes[this->model_res->version] + (4*shape_id)); + tmdl_shape *shape = (tmdl_shape*)((u32)this->model_res + shape_offset); + + if (this->model_res->version == 2) { + tmdl_materialv2 *materialv2 = (tmdl_materialv2*)((u32)this->model_res + shape->mat_offset); + this->setupMaterialGXv2(materialv2); + } else { + tmdl_material *material = (tmdl_material*)((u32)this->model_res + shape->mat_offset); + this->setupMaterialGX(material); + } + + void *pos_arr = (void*)((u32)this->model_res + shape->pos_arr_offset); + void *nrm_arr = (void*)((u32)this->model_res + shape->nrm_arr_offset); + void *uv_arr = (void*)((u32)this->model_res + shape->uv_arr_offset); + + GXSetArray(GX_VA_POS, pos_arr, 12); + GXSetArray(GX_VA_NRM, nrm_arr, 12); + GXSetArray(GX_VA_TEX0, uv_arr, 8); + + void *dl_ptr = (void*)((u32)this->model_res + shape->dl_offset); + GXCallDisplayList(dl_ptr, shape->dl_size); +} + +void Model::setupMaterialGXv2(tmdl_materialv2 *material) { + LastMaterial = 0; // reset this + + if (material->texture_id != 0xFFFFFFFF) { + GXSetChanMatColor(GX_COLOR0A0, White); + GXSetChanMatColor(GX_COLOR1A1, White); + + GXTexObj tex; + + TPLGetGXTexObjFromPalette(this->texture_res, &tex, material->texture_id); + GXInitTexObjWrapMode(&tex, GX_REPEAT, GX_REPEAT); + GXLoadTexObj(&tex, GX_TEXMAP0); + + GXSetNumTexGens(1); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); + + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); + + // TEV blending ops: + // First off, use the equivalent of GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE) + //GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_RASC, GX_CC_ZERO); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_RASA, GX_CA_ZERO); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + + // Then do the same for stage1, but blend TEVPREV with RASC/RASA + GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_RASC, GX_CC_CPREV, GX_CC_ZERO); + GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_RASA, GX_CA_APREV, GX_CA_ZERO); + GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + + } else { + GXSetChanMatColor(GX_COLOR0A0, material->mat_colour); + GXSetChanMatColor(GX_COLOR1A1, White); + + GXSetNumTexGens(0); + + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR1A1); + + // TEV blending ops: + // First stage becomes GX_PASSCLR + GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR); + + // Then blend this colour with RASA/RASC in the second stage + GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_RASC, GX_CC_CPREV, GX_CC_ZERO); + GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_RASA, GX_CA_APREV, GX_CA_ZERO); + GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + } +} +void Model::setupMaterialGX(tmdl_material *material) { + if (material == LastMaterial) + return; + + LastMaterial = material; // small optimisation + + if (material->texture_name[0] != 0) { + GXSetChanMatColor(GX_COLOR0A0, White); + GXSetChanMatColor(GX_COLOR1A1, White); + + GXLoadTexObj(&material->texobj, GX_TEXMAP0); + + GXSetNumTexGens(1); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); + + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR1A1); + + // TEV blending ops: + // First off, use the equivalent of GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE) + //GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_RASC, GX_CC_ZERO); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_RASA, GX_CA_ZERO); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + + // Then do the same for stage1, but blend TEVPREV with RASC/RASA + GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_RASC, GX_CC_CPREV, GX_CC_ZERO); + GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_RASA, GX_CA_APREV, GX_CA_ZERO); + GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + + } else { + GXSetChanMatColor(GX_COLOR0A0, material->mat_colour); + GXSetChanMatColor(GX_COLOR1A1, White); + + GXSetNumTexGens(0); + + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); + GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR1A1); + + // TEV blending ops: + // First stage becomes GX_PASSCLR + GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR); + + // Then blend this colour with RASA/RASC in the second stage + GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_RASC, GX_CC_CPREV, GX_CC_ZERO); + GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_RASA, GX_CA_APREV, GX_CA_ZERO); + GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + } +} + +// todo: try out GXInit and see if it fixes the issues +// if so, it's something in there +void DrawQueue() { + LastMaterial = NULL; + + GXInvalidateVtxCache(); + GXInvalidateTexAll(); + GXClearVtxDesc(); + + GXSetVtxDesc(GX_VA_POS, GX_INDEX16); + GXSetVtxDesc(GX_VA_NRM, GX_INDEX16); + GXSetVtxDesc(GX_VA_TEX0, GX_INDEX16); + + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + + GXSetCurrentMtx(GX_PNMTX0); + + GXRenderModeObj *rm = Hook_GetGXRenderModeObj(); + if (rm->field_rendering) + GXSetViewportJitter(0, 0, rm->fbWidth, rm->efbHeight, 0, 1, VIGetNextField()); + else + GXSetViewport(0, 0, rm->fbWidth, rm->efbHeight, 0, 1); + + GXSetProjection(Camera.projection_matrix, Camera.projection); + + GXSetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR); + GXSetCullMode(GX_CULL_FRONT); + GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + GXSetZCompLoc(GX_TRUE); + + GXSetNumTevStages(2); + GXSetTevDirect(GX_TEVSTAGE0); + GXSetTevDirect(GX_TEVSTAGE1); + + GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA); + + GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0); + GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0); + + /*GXInitLightDir(&light, 0, -1, 0); + GXInitLightSpot(&light, 45, GX_SP_COS); + GXInitLightDistAttn(&light, 30, 0.7, GX_DA_GENTLE);*/ + GXLightObj light, light2; + + Point3d lightPos = {0,-500.0,0}; + MTXMultVec(Camera.view_matrix, &lightPos, &lightPos); + + GXInitLightColor(&light, White); + GXInitLightPos(&light, lightPos.x, lightPos.y, lightPos.z); + GXLoadLightObjImm(&light, GX_LIGHT0); + + GXInitLightColor(&light2, White); + GXInitSpecularDir(&light2, 0.5, 0.5, 0); + GXInitLightShininess(&light2, 4.0f); + GXLoadLightObjImm(&light2, GX_LIGHT1); + + GXSetNumChans(2); + GXSetChanAmbColor(GX_COLOR0A0, (GXColor){128,128,128,255}); + GXSetChanAmbColor(GX_COLOR1A1, (GXColor){128,128,128,255}); + + GXSetChanCtrl(GX_COLOR0A0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0, GX_DF_CLAMP, GX_AF_NONE); + GXSetChanCtrl(GX_COLOR1A1, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT1, GX_DF_CLAMP, GX_AF_SPEC); + + GXSetFog(GX_FOG_NONE, 0, 0, 0, 0, (GXColor){0,0,0,0}); + + + for (int idx = 0; idx < RenderQueuePos; idx++) { + RenderQueue[idx].model->draw(&RenderQueue[idx]); + } + + RenderQueuePos = 0; + + + + // THIS IS JUST FOR TESTING + static bool isCreated = false; + static mTexture_c *tex[14]; + + if (!isCreated) { + isCreated = true; + + for (int i = 0; i < 14; i++) { + tex[i] = new mTexture_c(128, 8, GX_TF_RGBA8); + tex[i]->allocateBuffer(); + + for (int y = 0; y < 8; y++) { + for (int x = 0; x < 128; x++) { + tex[i]->plotPixel(x, y, (GXColor){255,106,0,255}); + } + } + + //tex[i]->makeLinearGradient(i >> 1, 's', 0, 128, Black, White, ((i & 1) != 0)); + tex[i]->makeLinearGradient(i >> 1, 's', 0, 128, (GXColor){255,106,0,255}, (GXColor){0,255,30,255}, false); + //tex[i]->plotPixel(0, 0, White); + //tex[i]->plotPixel(2, 2, White); + //tex[i]->plotPixel(4, 4, White); + tex[i]->flushDC(); + } + } + + Mtx matrix, inv_matrix; + MTXIdentity(matrix); + GXLoadPosMtxImm(matrix, GX_PNMTX0); + + MTXInverse(matrix, inv_matrix); + GXLoadNrmMtxImm(inv_matrix, GX_PNMTX0); + + GXSetChanMatColor(GX_COLOR0A0, White); + GXSetChanMatColor(GX_COLOR1A1, White); + + GXSetNumTexGens(1); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); + + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); + GXSetNumTevStages(1); + + // TEV blending ops: + // First off, use the equivalent of GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE) + GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE); + /*GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_RASC, GX_CC_ZERO); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_RASA, GX_CA_ZERO); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + + // Then do the same for stage1, but blend TEVPREV with RASC/RASA + GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_RASC, GX_CC_CPREV, GX_CC_ZERO); + GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_RASA, GX_CA_APREV, GX_CA_ZERO); + GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);*/ + + GXCullMode(GX_CULL_NONE); + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + + float y = -40.0f; + for (int i = 0; i < 14; i++) { + tex[i]->load(GX_TEXMAP0); + GXBegin(GX_QUADS, GX_VTXFMT0, 4); + + GXPosition3f32(-40.0f, y, -120.0f); + GXTexCoord2f32(0.0f, 1.0f); + GXPosition3f32(40.0f, y, -120.0f); + GXTexCoord2f32(1.0f, 1.0f); + GXPosition3f32(40.0f, y+5.0f, -120.0f); + GXTexCoord2f32(1.0f, 0.0f); + GXPosition3f32(-40.0f, y+5.0f, -120.0f); + GXTexCoord2f32(0.0f, 0.0f); + GXEnd(); + + y += 5.0f; + } +} + + + +namespace Util { + +/*void RotateToFace(const Vec &O, const Vec &P, const Vec &U, Mtx out) { + // http://forums.create.msdn.com/forums/p/10228/363692.aspx + Vec D, Right, Backwards, Up; + + VECSubtract(&O, &P, &D); + VECCrossProduct(&U, &D, &Right); + VECNormalize(&Right, &Right); + VECCrossProduct(&Right, &U, &Backwards); + VECNormalize(&Backwards, &Backwards); + VECCrossProduct(&Backwards, &Right, &Up); + + out[0][0] = Right.x; + out[0][1] = Right.y; + out[0][2] = Right.z; + out[0][3] = 0; + out[1][0] = Up.x; + out[1][1] = Up.y; + out[1][2] = Up.z; + out[1][3] = 0; + out[2][0] = Backwards.x; + out[2][1] = Backwards.y; + out[2][2] = Backwards.z; + out[2][3] = 0; +}*/ + + +}; + +}; + -- cgit v1.2.3