diff options
Diffstat (limited to '')
-rw-r--r-- | src/koopatlas/map.cpp | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/src/koopatlas/map.cpp b/src/koopatlas/map.cpp new file mode 100644 index 0000000..ef63eb1 --- /dev/null +++ b/src/koopatlas/map.cpp @@ -0,0 +1,259 @@ +#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); +} + |