mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-12 09:06:55 -04:00
Refactor isometric block drawing to only update the vertex buffer once
This commit is contained in:
parent
654ce2079b
commit
e2798dcebe
@ -10,7 +10,8 @@
|
||||
static float iso_scale;
|
||||
static struct VertexTextured* iso_vertices;
|
||||
static struct VertexTextured* iso_vertices_base;
|
||||
static GfxResourceID iso_vb;
|
||||
static int* iso_state;
|
||||
static int* iso_state_base;
|
||||
|
||||
static cc_bool iso_cacheInited;
|
||||
static PackedCol iso_color = PACKEDCOL_WHITE;
|
||||
@ -23,7 +24,6 @@ static PackedCol iso_colorXSide, iso_colorZSide, iso_colorYBottom;
|
||||
|
||||
static struct Matrix iso_transform;
|
||||
static Vec3 iso_pos;
|
||||
static int iso_lastTexIndex, iso_texIndex;
|
||||
|
||||
static void IsometricDrawer_RotateX(float cosA, float sinA) {
|
||||
float y = cosA * iso_pos.Y + sinA * iso_pos.Z;
|
||||
@ -50,35 +50,22 @@ static void IsometricDrawer_InitCache(void) {
|
||||
Matrix_Mul(&iso_transform, &rotY, &rotX);
|
||||
}
|
||||
|
||||
static void IsometricDrawer_Flush(void) {
|
||||
int count;
|
||||
if (iso_lastTexIndex != -1) {
|
||||
Gfx_BindTexture(Atlas1D.TexIds[iso_lastTexIndex]);
|
||||
count = (int)(iso_vertices - iso_vertices_base);
|
||||
Gfx_UpdateDynamicVb_IndexedTris(iso_vb, iso_vertices_base, count);
|
||||
}
|
||||
|
||||
iso_lastTexIndex = iso_texIndex;
|
||||
iso_vertices = iso_vertices_base;
|
||||
}
|
||||
|
||||
static TextureLoc IsometricDrawer_GetTexLoc(BlockID block, Face face) {
|
||||
TextureLoc loc = Block_Tex(block, face);
|
||||
iso_texIndex = Atlas1D_Index(loc);
|
||||
|
||||
if (iso_lastTexIndex != iso_texIndex) IsometricDrawer_Flush();
|
||||
*iso_state++ = Atlas1D_Index(loc);
|
||||
return loc;
|
||||
}
|
||||
|
||||
static void IsometricDrawer_SpriteZQuad(BlockID block, cc_bool firstPart) {
|
||||
int texIndex;
|
||||
TextureLoc loc = Block_Tex(block, FACE_ZMAX);
|
||||
TextureRec rec = Atlas1D_TexRec(loc, 1, &iso_texIndex);
|
||||
TextureRec rec = Atlas1D_TexRec(loc, 1, &texIndex);
|
||||
|
||||
struct VertexTextured v;
|
||||
float minX, maxX, minY, maxY;
|
||||
float x1, x2;
|
||||
|
||||
if (iso_lastTexIndex != iso_texIndex) IsometricDrawer_Flush();
|
||||
*iso_state++ = texIndex;
|
||||
v.Col = iso_color;
|
||||
Block_Tint(v.Col, block);
|
||||
|
||||
@ -100,14 +87,15 @@ static void IsometricDrawer_SpriteZQuad(BlockID block, cc_bool firstPart) {
|
||||
}
|
||||
|
||||
static void IsometricDrawer_SpriteXQuad(BlockID block, cc_bool firstPart) {
|
||||
int texIndex;
|
||||
TextureLoc loc = Block_Tex(block, FACE_XMAX);
|
||||
TextureRec rec = Atlas1D_TexRec(loc, 1, &iso_texIndex);
|
||||
TextureRec rec = Atlas1D_TexRec(loc, 1, &texIndex);
|
||||
|
||||
struct VertexTextured v;
|
||||
float minY, maxY, minZ, maxZ;
|
||||
float z1, z2;
|
||||
|
||||
if (iso_lastTexIndex != iso_texIndex) IsometricDrawer_Flush();
|
||||
*iso_state++ = texIndex;
|
||||
v.Col = iso_color;
|
||||
Block_Tint(v.Col, block);
|
||||
|
||||
@ -128,17 +116,17 @@ static void IsometricDrawer_SpriteXQuad(BlockID block, cc_bool firstPart) {
|
||||
v.Y = minY; v.V = rec.V2; *iso_vertices++ = v;
|
||||
}
|
||||
|
||||
void IsometricDrawer_BeginBatch(struct VertexTextured* vertices, GfxResourceID vb) {
|
||||
void IsometricDrawer_BeginBatch(struct VertexTextured* vertices, int* state) {
|
||||
IsometricDrawer_InitCache();
|
||||
iso_lastTexIndex = -1;
|
||||
iso_vertices = vertices;
|
||||
iso_vertices_base = vertices;
|
||||
iso_vb = vb;
|
||||
iso_state = state;
|
||||
iso_state_base = state;
|
||||
|
||||
Gfx_LoadMatrix(MATRIX_VIEW, &iso_transform);
|
||||
}
|
||||
|
||||
void IsometricDrawer_DrawBatch(BlockID block, float size, float x, float y) {
|
||||
void IsometricDrawer_AddBatch(BlockID block, float size, float x, float y) {
|
||||
cc_bool bright = Blocks.FullBright[block];
|
||||
Vec3 min, max;
|
||||
if (Blocks.Draw[block] == DRAW_GAS) return;
|
||||
@ -185,12 +173,38 @@ void IsometricDrawer_DrawBatch(BlockID block, float size, float x, float y) {
|
||||
}
|
||||
}
|
||||
|
||||
void IsometricDrawer_EndBatch(void) {
|
||||
if (iso_vertices != iso_vertices_base) {
|
||||
iso_lastTexIndex = iso_texIndex;
|
||||
IsometricDrawer_Flush();
|
||||
static void IsometricDrawer_Render(GfxResourceID vb) {
|
||||
int curIdx, batchBeg, batchLen;
|
||||
int count, i;
|
||||
|
||||
count = (int)(iso_vertices - iso_vertices_base);
|
||||
Gfx_SetDynamicVbData(vb, iso_vertices_base, count);
|
||||
|
||||
curIdx = iso_state_base[0];
|
||||
batchLen = 0;
|
||||
batchBeg = 0;
|
||||
|
||||
for (i = 0; i < count / 4; i++, batchLen += 4)
|
||||
{
|
||||
if (iso_state_base[i] == curIdx) continue;
|
||||
|
||||
/* Flush previous batch */
|
||||
Gfx_BindTexture(Atlas1D.TexIds[curIdx]);
|
||||
Gfx_DrawVb_IndexedTris_Range(batchLen, batchBeg);
|
||||
|
||||
/* Reset for next batch */
|
||||
curIdx = iso_state_base[i];
|
||||
batchBeg = i * 4;
|
||||
batchLen = 0;
|
||||
}
|
||||
|
||||
iso_lastTexIndex = -1;
|
||||
Gfx_BindTexture(Atlas1D.TexIds[curIdx]);
|
||||
Gfx_DrawVb_IndexedTris_Range(batchLen, batchBeg);
|
||||
}
|
||||
|
||||
void IsometricDrawer_EndBatch(GfxResourceID vb) {
|
||||
if (iso_state != iso_state_base) {
|
||||
IsometricDrawer_Render(vb);
|
||||
}
|
||||
Gfx_LoadIdentityMatrix(MATRIX_VIEW);
|
||||
}
|
||||
|
@ -8,10 +8,11 @@ struct VertexTextured;
|
||||
|
||||
/* Maximum number of vertices used to draw a block in isometric way. */
|
||||
#define ISOMETRICDRAWER_MAXVERTICES 16
|
||||
|
||||
/* Sets up state to begin drawing blocks isometrically. */
|
||||
void IsometricDrawer_BeginBatch(struct VertexTextured* vertices, GfxResourceID vb);
|
||||
void IsometricDrawer_BeginBatch(struct VertexTextured* vertices, int* state);
|
||||
/* Buffers the vertices needed to draw the given block at the given position. */
|
||||
void IsometricDrawer_DrawBatch(BlockID block, float size, float x, float y);
|
||||
void IsometricDrawer_AddBatch(BlockID block, float size, float x, float y);
|
||||
/* Flushes buffered vertices to the GPU, then restores state. */
|
||||
void IsometricDrawer_EndBatch(void);
|
||||
void IsometricDrawer_EndBatch(GfxResourceID vb);
|
||||
#endif
|
||||
|
@ -403,13 +403,15 @@ static void HotbarWidget_RenderHotbarOutline(struct HotbarWidget* w) {
|
||||
Gfx_Draw2DTexture(&w->selTex, PACKEDCOL_WHITE);
|
||||
}
|
||||
|
||||
#define HOTBAR_MAX_VERTICES (INVENTORY_BLOCKS_PER_HOTBAR * ISOMETRICDRAWER_MAXVERTICES)
|
||||
static void HotbarWidget_RenderHotbarBlocks(struct HotbarWidget* w) {
|
||||
/* TODO: Should hotbar use its own VB? */
|
||||
struct VertexTextured vertices[INVENTORY_BLOCKS_PER_HOTBAR * ISOMETRICDRAWER_MAXVERTICES];
|
||||
struct VertexTextured vertices[HOTBAR_MAX_VERTICES];
|
||||
int state[HOTBAR_MAX_VERTICES / 4];
|
||||
float scale;
|
||||
int i, x, y;
|
||||
|
||||
IsometricDrawer_BeginBatch(vertices, Models.Vb);
|
||||
IsometricDrawer_BeginBatch(vertices, state);
|
||||
scale = w->elemSize / 2.0f;
|
||||
|
||||
for (i = 0; i < INVENTORY_BLOCKS_PER_HOTBAR; i++) {
|
||||
@ -419,9 +421,9 @@ static void HotbarWidget_RenderHotbarBlocks(struct HotbarWidget* w) {
|
||||
#ifdef CC_BUILD_TOUCH
|
||||
if (i == HOTBAR_MAX_INDEX && Input_TouchMode) continue;
|
||||
#endif
|
||||
IsometricDrawer_DrawBatch(Inventory_Get(i), scale, x, y);
|
||||
IsometricDrawer_AddBatch(Inventory_Get(i), scale, x, y);
|
||||
}
|
||||
IsometricDrawer_EndBatch();
|
||||
IsometricDrawer_EndBatch(Models.Vb);
|
||||
}
|
||||
|
||||
static int HotbarWidget_ScrolledIndex(struct HotbarWidget* w, float delta, int index, int dir) {
|
||||
@ -700,6 +702,7 @@ void TableWidget_RecreateBlocks(struct TableWidget* w) {
|
||||
static void TableWidget_Render(void* widget, double delta) {
|
||||
struct TableWidget* w = (struct TableWidget*)widget;
|
||||
struct VertexTextured vertices[TABLE_MAX_VERTICES];
|
||||
int state[TABLE_MAX_VERTICES / 4];
|
||||
int cellSizeX, cellSizeY, size;
|
||||
float off;
|
||||
int i, x, y;
|
||||
@ -732,14 +735,14 @@ static void TableWidget_Render(void* widget, double delta) {
|
||||
}
|
||||
Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED);
|
||||
|
||||
IsometricDrawer_BeginBatch(vertices, w->vb);
|
||||
IsometricDrawer_BeginBatch(vertices, state);
|
||||
for (i = 0; i < w->blocksCount; i++) {
|
||||
if (!TableWidget_GetCoords(w, i, &x, &y)) continue;
|
||||
|
||||
/* We want to always draw the selected block on top of others */
|
||||
/* TODO: Need two size arguments, in case X/Y dpi differs */
|
||||
if (i == w->selectedIndex) continue;
|
||||
IsometricDrawer_DrawBatch(w->blocks[i],
|
||||
IsometricDrawer_AddBatch(w->blocks[i],
|
||||
w->normBlockSize, x + cellSizeX / 2, y + cellSizeY / 2);
|
||||
}
|
||||
|
||||
@ -747,10 +750,10 @@ static void TableWidget_Render(void* widget, double delta) {
|
||||
if (i != -1) {
|
||||
TableWidget_GetCoords(w, i, &x, &y);
|
||||
|
||||
IsometricDrawer_DrawBatch(w->blocks[i],
|
||||
IsometricDrawer_AddBatch(w->blocks[i],
|
||||
w->selBlockSize, x + cellSizeX / 2, y + cellSizeY / 2);
|
||||
}
|
||||
IsometricDrawer_EndBatch();
|
||||
IsometricDrawer_EndBatch(w->vb);
|
||||
}
|
||||
|
||||
static void TableWidget_Free(void* widget) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user