#include "koopatlas/map.h" #include "koopatlas/camera.h" //#define TILE_DEBUGGING //#define BOUND_DEBUGGING #ifdef TILE_DEBUGGING #define TileReport OSReport #else inline void TileReport(const char *str, ...) { } #endif #ifdef BOUND_DEBUGGING #define BoundReport OSReport #else inline void BoundReport(const char *str, ...) { } #endif dWMMap_c *dWMMap_c::instance = 0; dWMMap_c *dWMMap_c::build() { OSReport("Creating WM_Map\n"); void *buffer = AllocFromGameHeap1(sizeof(dWMMap_c)); dWMMap_c *c = new(buffer) dWMMap_c; OSReport("Created WM_Map @ %p\n", c); instance = c; return c; } dWMMap_c::dWMMap_c() { } int dWMMap_c::onCreate() { renderer.allocator.setup(GameHeaps[0], 0x20); OSReport("Setting up Renderer\n"); bool result = renderer.setup(&renderer.allocator); if (result) OSReport("Set up Renderer\n"); else OSReport(":(\n"); return true; } int dWMMap_c::onDelete() { return true; } int dWMMap_c::onExecute() { return true; } int dWMMap_c::onDraw() { renderer.scheduleForDrawing(); return true; } void dWMMap_c::renderer_c::drawOpa() { //drawTiles(); } void dWMMap_c::renderer_c::drawXlu() { drawTiles(); } void dWMMap_c::renderer_c::drawTiles() { beginRendering(); dKPMapData_c *dataCls = &dScKoopatlas_c::instance->mapData; dKPMapFile_s *data = dataCls->data; baseZ = 1000 - (10 * data->layerCount); for (int iLayer = data->layerCount - 1; iLayer >= 0; iLayer--) { dKPLayer_s *layer = data->layers[iLayer]; TileReport("Checking layer %d with type %d\n", iLayer, layer->type); if (layer->type == dKPLayer_s::OBJECTS) renderTileLayer(layer, data->sectors); } endRendering(); } void dWMMap_c::renderer_c::beginRendering() { currentTexture = 0; nw4r::g3d::Camera cam3d(GetCameraByID(0)); cam3d.GetCameraMtx(&renderMtx); MTXTransApply(renderMtx, renderMtx, 0, 0, baseZ); /*OSReport("MTX:\n"); OSReport("%f, %f, %f, %f:\n", renderMtx[0][0], renderMtx[0][1], renderMtx[0][2], renderMtx[0][3]); OSReport("%f, %f, %f, %f:\n", renderMtx[1][0], renderMtx[1][1], renderMtx[1][2], renderMtx[1][3]); OSReport("%f, %f, %f, %f:\n", renderMtx[2][0], renderMtx[2][1], renderMtx[2][2], renderMtx[2][3]);//*/ GXSetCurrentMtx(GX_PNMTX0); dWorldCamera_c *camObj = dWorldCamera_c::instance; minX = ((int)camObj->screenLeft) / 16; minY = ((int)(-camObj->screenTop)) / 16; maxX = (((int)(camObj->screenLeft + camObj->screenWidth)) + 15) / 16; maxY = (((int)(-camObj->screenTop + camObj->screenHeight)) + 15) / 16; GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_S16, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_U8, 8); GXSetNumIndStages(0); for (int i = 0; i < 0x10; i++) GXSetTevDirect((GXTevStageID)i); GXSetNumChans(0); GXSetNumTexGens(1); GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); GXSetNumTevStages(1); GXSetNumIndStages(0); GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_C1, GX_CC_C0, GX_CC_TEXC, GX_CC_ZERO); GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO); GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); GXSetZCompLoc(GX_FALSE); GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET); GXSetZMode(GX_TRUE, GX_LEQUAL, GX_FALSE); GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_OR, GX_GREATER, 0); GXSetFog(GX_FOG_NONE, 0, 0, 0, 0, (GXColor){0,0,0,0}); GXSetFogRangeAdj(GX_FALSE, 0, 0); GXSetCullMode(GX_CULL_NONE); GXSetDither(GX_TRUE); GXSetTevColor(GX_TEVREG0, (GXColor){255,255,255,255}); GXSetTevColor(GX_TEVREG1, (GXColor){0,0,0,255}); } void dWMMap_c::renderer_c::renderTileLayer(dKPLayer_s *layer, dKPLayer_s::sector_s *sectors) { //TileReport("Rendering layer %p\n", layer); renderMtx[2][3] += 10; // don't render it if we don't need to if (maxX < layer->left || minX > layer->right) return; if (maxY < layer->top || minY > layer->bottom) return; // set up loadCamera(); loadTexture(layer->tileset); // figure out -what- to render BoundReport("Regular render area: %d,%d to %d,%d\n", minX, minY, maxX, maxY); BoundReport("Layer bounds: %d,%d to %d,%d\n", layer->left, layer->top, layer->right, layer->bottom); int toRenderMinX = max(minX, layer->left); int toRenderMinY = max(minY, layer->top); int toRenderMaxX = min(maxX, layer->right); int toRenderMaxY = min(maxY, layer->bottom); int sectorBaseX = layer->sectorLeft; int sectorBaseY = layer->sectorTop; int sectorIndexStride = (layer->sectorRight - layer->sectorLeft + 1); int sectorMinX = toRenderMinX / 16; int sectorMinY = toRenderMinY / 16; int sectorMaxX = toRenderMaxX / 16; int sectorMaxY = toRenderMaxY / 16; BoundReport("To render: %d,%d to %d,%d\n", toRenderMinX, toRenderMinY, toRenderMaxX, toRenderMaxY); BoundReport("sectors %d,%d to %d,%d\n", sectorMinX, sectorMinY, sectorMaxX, sectorMaxY); for (int sectorY = sectorMinY; sectorY <= sectorMaxY; sectorY++) { int baseIndex = (sectorY - sectorBaseY) * sectorIndexStride; int iMinY = (sectorY == sectorMinY) ? (toRenderMinY & 0xF) : 0; int iMaxY = (sectorY == sectorMaxY) ? (toRenderMaxY & 0xF) : 15; int worldSectorY = sectorY << 4; for (int sectorX = sectorMinX; sectorX <= sectorMaxX; sectorX++) { u16 index = layer->indices[baseIndex + sectorX - sectorBaseX]; TileReport("Sector index @ %d,%d: %d\n", sectorX, sectorY, index); if (index == 0xFFFF) continue; dKPLayer_s::sector_s *sector = §ors[index]; int iMinX = (sectorX == sectorMinX) ? (toRenderMinX & 0xF) : 0; int iMaxX = (sectorX == sectorMaxX) ? (toRenderMaxX & 0xF) : 15; TileReport("Min/Max: X: %d,%d Y: %d,%d\n", iMinX, iMaxX, iMinY, iMaxY); int worldSectorX = sectorX << 4; for (int inY = iMinY; inY <= iMaxY; inY++) { for (int inX = iMinX; inX <= iMaxX; inX++) { u16 tileID = (*sector)[inY][inX]; if (tileID == 0xFFFF) continue; s16 worldX = (worldSectorX | inX) << 4; s16 worldY = -((worldSectorY | inY) << 4); u8 tileX = (tileID & 0x1F) * 8; u8 tileY = ((tileID & 0x1E0) / 32) * 16; TileReport("Drawing tile %d at %d,%d\n", tileID, worldX, worldY); GXBegin(GX_QUADS, GX_VTXFMT0, 4); GXPosition2s16(worldX + 16, worldY - 16); GXTexCoord2u8(tileX + 7, tileY + 14); GXPosition2s16(worldX + 16, worldY); GXTexCoord2u8(tileX + 7, tileY + 2); GXPosition2s16(worldX, worldY); GXTexCoord2u8(tileX + 1, tileY + 2); GXPosition2s16(worldX, worldY - 16); GXTexCoord2u8(tileX + 1, tileY + 14);//*/ GXEnd(); } } TileReport("Sector complete\n"); } } //TileReport("Layer complete\n"); } void dWMMap_c::renderer_c::endRendering() { } void dWMMap_c::renderer_c::loadTexture(GXTexObj *obj) { if (currentTexture == obj) return; GXLoadTexObj(obj, GX_TEXMAP0); currentTexture = obj; } void dWMMap_c::renderer_c::loadCamera() { GXLoadPosMtxImm(renderMtx, GX_PNMTX0); }