mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-24 05:10:42 -04:00
Port IsometricBlockDrawer to C.
This commit is contained in:
parent
5a60670ba1
commit
8e425763c7
@ -19,7 +19,6 @@ namespace ClassicalSharp {
|
||||
TerrainAtlas1D atlas;
|
||||
int index;
|
||||
float scale;
|
||||
bool bright;
|
||||
VertexP3fT2fC4b[] vertices;
|
||||
int vb;
|
||||
|
||||
@ -60,7 +59,7 @@ namespace ClassicalSharp {
|
||||
drawer.elementsPerAtlas1D = atlas.elementsPerAtlas1D;
|
||||
drawer.invVerElementSize = atlas.invElementSize;
|
||||
|
||||
bright = info.FullBright[block];
|
||||
bool bright = info.FullBright[block];
|
||||
if (info.Draw[block] == DrawType.Gas) return;
|
||||
|
||||
// isometric coords size: cosY * -scale - sinY * scale
|
||||
@ -68,8 +67,8 @@ namespace ClassicalSharp {
|
||||
scale = size / (2 * cosY);
|
||||
// screen to isometric coords (cos(-x) = cos(x), sin(-x) = -sin(x))
|
||||
pos.X = x; pos.Y = y; pos.Z = 0;
|
||||
Utils.RotateX(ref pos.Y, ref pos.Z, cosX, -sinX);
|
||||
Utils.RotateY(ref pos.X, ref pos.Z, cosY, -sinY);
|
||||
RotateX(cosX, -sinX);
|
||||
RotateY(cosY, -sinY);
|
||||
|
||||
// See comment in IGraphicsApi.Draw2DTexture()
|
||||
pos.X -= 0.5f; pos.Y -= 0.5f;
|
||||
@ -81,8 +80,8 @@ namespace ClassicalSharp {
|
||||
SpriteZQuad(block, false);
|
||||
SpriteXQuad(block, false);
|
||||
} else {
|
||||
drawer.minBB = info.MinBB[block]; drawer.minBB.Y = 1 - drawer.minBB.Y;
|
||||
drawer.maxBB = info.MaxBB[block]; drawer.maxBB.Y = 1 - drawer.maxBB.Y;
|
||||
drawer.minBB = info.MinBB[block]; drawer.minBB.Y = 1 - drawer.minBB.Y;
|
||||
drawer.maxBB = info.MaxBB[block]; drawer.maxBB.Y = 1 - drawer.maxBB.Y;
|
||||
|
||||
Vector3 min = info.MinBB[block], max = info.MaxBB[block];
|
||||
drawer.x1 = scale * (1 - min.X * 2) + pos.X; drawer.x2 = scale * (1 - max.X * 2) + pos.X;
|
||||
@ -127,7 +126,7 @@ namespace ClassicalSharp {
|
||||
|
||||
if (game.BlockInfo.Tinted[block]) {
|
||||
v.Colour = Utils.Tint(v.Colour, game.BlockInfo.FogColour[block]);
|
||||
}
|
||||
}
|
||||
|
||||
float x1 = firstPart ? 0.5f : -0.1f, x2 = firstPart ? 1.1f : 0.5f;
|
||||
rec.U1 = firstPart ? 0.0f : 0.5f; rec.U2 = (firstPart ? 0.5f : 1.0f) * (15.99f/16f);
|
||||
@ -173,5 +172,19 @@ namespace ClassicalSharp {
|
||||
lastIndex = texIndex;
|
||||
game.Graphics.BindTexture(atlas.TexIds[texIndex]);
|
||||
}
|
||||
|
||||
/// <summary> Rotates the given 3D coordinates around the x axis. </summary>
|
||||
static void RotateX(float cosA, float sinA) {
|
||||
float y = cosA * pos.Y + sinA * pos.Z;
|
||||
pos.Z = -sinA * pos.Y + cosA * pos.Z;
|
||||
pos.Y = y;
|
||||
}
|
||||
|
||||
/// <summary> Rotates the given 3D coordinates around the y axis. </summary>
|
||||
static void RotateY(float cosA, float sinA) {
|
||||
float x = cosA * pos.X - sinA * pos.Z;
|
||||
pos.Z = sinA * pos.X + cosA * pos.Z;
|
||||
pos.X = x;
|
||||
}
|
||||
}
|
||||
}
|
@ -80,23 +80,7 @@ namespace ClassicalSharp {
|
||||
public static Vector3 RotateZ(Vector3 v, float angle) {
|
||||
float cosA = (float)Math.Cos(angle), sinA = (float)Math.Sin(angle);
|
||||
return new Vector3(cosA * v.X + sinA * v.Y, -sinA * v.X + cosA * v.Y, v.Z);
|
||||
}
|
||||
|
||||
/// <summary> Rotates the given 3D coordinates around the x axis. </summary>
|
||||
public static void RotateX(ref float y, ref float z, float cosA, float sinA) {
|
||||
float y2 = cosA * y + sinA * z; z = -sinA * y + cosA * z; y = y2;
|
||||
}
|
||||
|
||||
/// <summary> Rotates the given 3D coordinates around the y axis. </summary>
|
||||
public static void RotateY(ref float x, ref float z, float cosA, float sinA) {
|
||||
float x2 = cosA * x - sinA * z; z = sinA * x + cosA * z; x = x2;
|
||||
}
|
||||
|
||||
/// <summary> Rotates the given 3D coordinates around the z axis. </summary>
|
||||
public static void RotateZ(ref float x, ref float y, float cosA, float sinA) {
|
||||
float x2 = cosA * x + sinA * y; y = -sinA * x + cosA * y; x = x2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary> Returns the square of the euclidean distance between two points. </summary>
|
||||
public static float DistanceSquared(Vector3 p1, Vector3 p2) {
|
||||
|
@ -195,6 +195,7 @@
|
||||
<ClInclude Include="GZipHeader.h" />
|
||||
<ClInclude Include="Intersection.h" />
|
||||
<ClInclude Include="IO.h" />
|
||||
<ClInclude Include="IsometricDrawer.h" />
|
||||
<ClInclude Include="Lighting.h" />
|
||||
<ClInclude Include="BordersRenderer.h" />
|
||||
<ClInclude Include="LiquidAnimations.h" />
|
||||
@ -264,6 +265,7 @@
|
||||
<ClCompile Include="GameStructs.c" />
|
||||
<ClCompile Include="GZipHeader.c" />
|
||||
<ClCompile Include="Intersection.c" />
|
||||
<ClCompile Include="IsometricDrawer.c" />
|
||||
<ClCompile Include="Lighting.c" />
|
||||
<ClCompile Include="LiquidAnimations.c" />
|
||||
<ClCompile Include="MapRenderer.c" />
|
||||
|
@ -363,6 +363,9 @@
|
||||
<ClInclude Include="TreeGen.h">
|
||||
<Filter>Header Files\Generator</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IsometricDrawer.h">
|
||||
<Filter>Header Files\2D</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="NotchyGenerator.c">
|
||||
@ -521,5 +524,8 @@
|
||||
<ClCompile Include="TreeGen.c">
|
||||
<Filter>Source Files\Generator</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IsometricDrawer.c">
|
||||
<Filter>Source Files\2D</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
190
src/Client/IsometricDrawer.c
Normal file
190
src/Client/IsometricDrawer.c
Normal file
@ -0,0 +1,190 @@
|
||||
#include "IsometricDrawer.h"
|
||||
#include "Drawer.h"
|
||||
#include "GraphicsCommon.h"
|
||||
#include "GraphicsAPI.h"
|
||||
#include "Matrix.h"
|
||||
#include "PackedCol.h"
|
||||
#include "ExtMath.h"
|
||||
#include "Block.h"
|
||||
#include "BlockEnums.h"
|
||||
#include "TerrainAtlas1D.h"
|
||||
|
||||
Int32 iso_count;
|
||||
Real32 iso_scale;
|
||||
VertexP3fT2fC4b* iso_vertices;
|
||||
Int32 iso_vb;
|
||||
|
||||
bool iso_cacheInitalisesd;
|
||||
PackedCol iso_colNormal, iso_colXSide, iso_colZSide, iso_colYBottom;
|
||||
Real32 iso_cosX, iso_sinX, iso_cosY, iso_sinY;
|
||||
Matrix iso_transform;
|
||||
|
||||
Vector3 iso_pos;
|
||||
Int32 iso_last1DIndex, iso_1DIndex;
|
||||
|
||||
void IsometricDrawer_BeginBatch(VertexP3fT2fC4b* vertices, GfxResourceID vb) {
|
||||
IsometricDrawer_InitCache();
|
||||
iso_last1DIndex = -1;
|
||||
iso_count = 0;
|
||||
iso_vertices = vertices;
|
||||
iso_vb = vb;
|
||||
|
||||
Gfx_PushMatrix();
|
||||
Gfx_MultiplyMatrix(&iso_transform);
|
||||
}
|
||||
|
||||
void IsometricDrawer_DrawBatch(BlockID block, Real32 size, Real32 x, Real32 y) {
|
||||
bool bright = Block_FullBright[block];
|
||||
if (Block_Draw[block] == DrawType_Gas) return;
|
||||
|
||||
/* isometric coords size: cosY * -scale - sinY * scale */
|
||||
/* we need to divide by (2 * cosY), as the calling function expects size to be in pixels. */
|
||||
iso_scale = size / (2.0f * iso_cosY);
|
||||
|
||||
/* screen to isometric coords (cos(-x) = cos(x), sin(-x) = -sin(x)) */
|
||||
iso_pos.X = x; iso_pos.Y = y; iso_pos.Z = 0.0f;
|
||||
IsometricDrawer_RotateX(iso_cosX, -iso_sinX);
|
||||
IsometricDrawer_RotateY(iso_cosY, -iso_sinY);
|
||||
|
||||
/* See comment in GfxCommon_Draw2DTexture() */
|
||||
iso_pos.X -= 0.5f; iso_pos.Y -= 0.5f;
|
||||
|
||||
if (Block_Draw[block] == DrawType_Sprite) {
|
||||
SpriteXQuad(block, true);
|
||||
SpriteZQuad(block, true);
|
||||
|
||||
SpriteZQuad(block, false);
|
||||
SpriteXQuad(block, false);
|
||||
} else {
|
||||
Drawer_MinBB = Block_MinBB[block]; Drawer_MinBB.Y = 1.0f - Drawer_MinBB.Y;
|
||||
Drawer_MaxBB = Block_MaxBB[block]; Drawer_MaxBB.Y = 1.0f - Drawer_MaxBB.Y;
|
||||
Vector3 min = Block_MinBB[block], max = Block_MaxBB[block];
|
||||
|
||||
Drawer_X1 = iso_scale * (1.0f - min.X * 2.0f) + iso_pos.X;
|
||||
Drawer_X2 = iso_scale * (1.0f - max.X * 2.0f) + iso_pos.X;
|
||||
Drawer_Y1 = iso_scale * (1.0f - min.Y * 2.0f) + iso_pos.Y;
|
||||
Drawer_Y2 = iso_scale * (1.0f - max.Y * 2.0f) + iso_pos.Y;
|
||||
Drawer_Z1 = iso_scale * (1.0f - min.Z * 2.0f) + iso_pos.Z;
|
||||
Drawer_Z2 = iso_scale * (1.0f - max.Z * 2.0f) + iso_pos.Z;
|
||||
|
||||
Drawer_Tinted = Block_Tinted[block];
|
||||
Drawer_TintColour = Block_FogColour[block];
|
||||
|
||||
Drawer_XMax(1, bright ? iso_colNormal : iso_colXSide,
|
||||
IsometricDrawer_GetTex(block, Face_XMax), &iso_vertices);
|
||||
Drawer_ZMin(1, bright ? iso_colNormal : iso_colZSide,
|
||||
IsometricDrawer_GetTex(block, Face_ZMin), &iso_vertices);
|
||||
Drawer_YMax(1, iso_colNormal,
|
||||
IsometricDrawer_GetTex(block, Face_YMax), &iso_vertices);
|
||||
iso_count += 4 * 3;
|
||||
}
|
||||
}
|
||||
|
||||
void IsometricDrawer_EndBatch(void) {
|
||||
if (iso_count > 0) {
|
||||
if (iso_1DIndex != iso_last1DIndex) Gfx_BindTexture(Atlas1D_TexIds[iso_1DIndex]);
|
||||
GfxCommon_UpdateDynamicIndexedVb(DrawMode_Triangles, iso_vb, iso_vertices, iso_count);
|
||||
|
||||
iso_count = 0;
|
||||
iso_last1DIndex = -1;
|
||||
}
|
||||
Gfx_PopMatrix();
|
||||
}
|
||||
|
||||
|
||||
void IsometricDrawer_InitCache(void) {
|
||||
if (iso_cacheInitalisesd) return;
|
||||
iso_cacheInitalisesd = true;
|
||||
iso_colNormal = PackedCol_White;
|
||||
PackedCol_GetShaded(iso_colNormal, &iso_colXSide, &iso_colZSide, &iso_colYBottom);
|
||||
|
||||
Matrix rotY, rotX;
|
||||
Matrix_RotateY(&rotY, 45.0f * MATH_DEG2RAD);
|
||||
Matrix_RotateX(&rotX, -30.0f * MATH_DEG2RAD);
|
||||
Matrix_Mul(&iso_transform, &rotY, &rotX);
|
||||
|
||||
iso_cosX = Math_Cos(30.0f * MATH_DEG2RAD);
|
||||
iso_sinX = Math_Sin(30.0f * MATH_DEG2RAD);
|
||||
iso_cosY = Math_Cos(-45.0f * MATH_DEG2RAD);
|
||||
iso_sinY = Math_Sin(-45.0f * MATH_DEG2RAD);
|
||||
}
|
||||
|
||||
|
||||
TextureLoc IsometricDrawer_GetTexLoc(BlockID block, Face face) {
|
||||
TextureLoc texLoc = Block_GetTexLoc(block, face);
|
||||
iso_1DIndex = Atlas1D_Index(texLoc);
|
||||
|
||||
if (iso_last1DIndex != iso_1DIndex) Flush();
|
||||
return texLoc;
|
||||
}
|
||||
|
||||
#define AddVertex *iso_vertices = v; iso_vertices++;
|
||||
void IsometricDrawer_SpriteZQuad(BlockID block, bool firstPart) {
|
||||
TextureLoc texLoc = Block_GetTexLoc(block, Face_XMax);
|
||||
TextureRec rec = Atlas1D_TexRec(texLoc, 1, &iso_1DIndex);
|
||||
if (iso_last1DIndex != iso_1DIndex) Flush();
|
||||
|
||||
VertexP3fT2fC4b v;
|
||||
v.Colour = iso_colNormal;
|
||||
Block_Tint(v.Colour, block);
|
||||
|
||||
Real32 x1 = firstPart ? 0.5f : -0.1f, x2 = firstPart ? 1.1f : 0.5f;
|
||||
rec.U1 = firstPart ? 0.0f : 0.5f;
|
||||
rec.U2 = (firstPart ? 0.5f : 1.0f) * UV2_Scale;
|
||||
|
||||
Real32 minX = iso_scale * (1.0f - x1 * 2.0f) + iso_pos.X;
|
||||
Real32 maxX = iso_scale * (1.0f - x2 * 2.0f) + iso_pos.X;
|
||||
Real32 minY = iso_scale * (1.0f - 0.0f * 2.0f) + iso_pos.Y;
|
||||
Real32 maxY = iso_scale * (1.0f - 1.1f * 2.0f) + iso_pos.Y;
|
||||
|
||||
v.X = minX; v.Y = minY; v.Z = iso_pos.Z; v.U = rec.U2; v.V = rec.V2; AddVertex
|
||||
v.X = minX; v.Y = maxY; v.Z = iso_pos.Z; v.U = rec.U2; v.V = rec.V1; AddVertex
|
||||
v.X = maxX; v.Y = maxY; v.Z = iso_pos.Z; v.U = rec.U1; v.V = rec.V1; AddVertex
|
||||
v.X = maxX; v.Y = minY; v.Z = iso_pos.Z; v.U = rec.U1; v.V = rec.V2; AddVertex
|
||||
}
|
||||
|
||||
void IsometricDrawer_SpriteXQuad(BlockID block, bool firstPart) {
|
||||
TextureLoc texLoc = Block_GetTexLoc(block, Face_XMax);
|
||||
TextureRec rec = Atlas1D_TexRec(texLoc, 1, &iso_1DIndex);
|
||||
if (iso_last1DIndex != iso_1DIndex) Flush();
|
||||
|
||||
VertexP3fT2fC4b v;
|
||||
v.Colour = iso_colNormal;
|
||||
Block_Tint(v.Colour, block);
|
||||
|
||||
Real32 z1 = firstPart ? 0.5f : -0.1f, z2 = firstPart ? 1.1f : 0.5f;
|
||||
rec.U1 = firstPart ? 0.0f : 0.5f;
|
||||
rec.U2 = (firstPart ? 0.5f : 1.0f) * UV2_Scale;
|
||||
|
||||
Real32 minY = iso_scale * (1.0f - 0.0f * 2.0f) + iso_pos.Y;
|
||||
Real32 maxY = iso_scale * (1.0f - 1.1f * 2.0f) + iso_pos.Y;
|
||||
Real32 minZ = iso_scale * (1.0f - z1 * 2.0f) + iso_pos.Z;
|
||||
Real32 maxZ = iso_scale * (1.0f - z2 * 2.0f) + iso_pos.Z;
|
||||
|
||||
v.X = iso_pos.X; v.Y = minY; v.Z = minZ; v.U = rec.U2; v.V = rec.V2; AddVertex
|
||||
v.X = iso_pos.X; v.Y = maxY; v.Z = minZ; v.U = rec.U2; v.V = rec.V1; AddVertex
|
||||
v.X = iso_pos.X; v.Y = maxY; v.Z = maxZ; v.U = rec.U1; v.V = rec.V1; AddVertex
|
||||
v.X = iso_pos.X; v.Y = minY; v.Z = maxZ; v.U = rec.U1; v.V = rec.V2; AddVertex
|
||||
}
|
||||
|
||||
void IsometricDrawer_Flush(void) {
|
||||
if (iso_last1DIndex != -1) {
|
||||
GfxCommon_UpdateDynamicIndexedVb(DrawMode_Triangles, iso_vb, iso_vertices, iso_count);
|
||||
iso_count = 0;
|
||||
}
|
||||
|
||||
iso_last1DIndex = iso_1DIndex;
|
||||
Gfx_BindTexture(Atlas1D_TexIds[iso_1DIndex]);
|
||||
}
|
||||
|
||||
static void IsometricDrawer_RotateX(Real32 cosA, Real32 sinA) {
|
||||
Real32 y = cosA * iso_pos.Y + sinA * iso_pos.Z;
|
||||
iso_pos.Z = -sinA * iso_pos.Y + cosA * iso_pos.Z;
|
||||
iso_pos.Y = y;
|
||||
}
|
||||
|
||||
static void IsometricDrawer_RotateY(Real32 cosA, Real32 sinA) {
|
||||
Real32 x = cosA * iso_pos.X - sinA * iso_pos.Z;
|
||||
iso_pos.Z = sinA * iso_pos.X + cosA * iso_pos.Z;
|
||||
iso_pos.X = x;
|
||||
}
|
43
src/Client/IsometricDrawer.h
Normal file
43
src/Client/IsometricDrawer.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef CS_ISOMETRICDRAWER_H
|
||||
#define CS_ISOMETRICDRAWER_H
|
||||
#include "Typedefs.h"
|
||||
#include "GraphicsEnums.h"
|
||||
#include "VertexStructs.h"
|
||||
#include "BlockEnums.h"
|
||||
/* Draws 2D isometric blocks for the hotbar and inventory UIs.
|
||||
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
||||
*/
|
||||
|
||||
/* Sets up state for drawing a batch of isometric blocks. */
|
||||
void IsometricDrawer_BeginBatch(VertexP3fT2fC4b* vertices, GfxResourceID vb);
|
||||
|
||||
/* Adds a block to the current batch. */
|
||||
void IsometricDrawer_DrawBatch(BlockID block, Real32 size, Real32 x, Real32 y);
|
||||
|
||||
/* Finishes drawing a batch of isometric blocks. */
|
||||
void IsometricDrawer_EndBatch(void);
|
||||
|
||||
|
||||
/* Calculates cached variables used for batching. (rotation, transform matrices) */
|
||||
static void IsometricDrawer_InitCache(void);
|
||||
|
||||
/* Gets texture of given face of block, flushing the batch to the GPU
|
||||
if the texture is in a different 1D atlas than the previous items. */
|
||||
static TextureLoc IsometricDrawer_GetTexLoc(BlockID block, Face face);
|
||||
|
||||
static void IsometricDrawer_SpriteZQuad(BlockID block, bool firstPart);
|
||||
|
||||
static void IsometricDrawer_SpriteXQuad(BlockID block, bool firstPart);
|
||||
|
||||
/* Flushes the current batch to the GPU, used when next item in the batch
|
||||
uses a different 1D texture atlas than the previous items. */
|
||||
static void IsometricDrawer_Flush(void);
|
||||
|
||||
|
||||
/* Rotates the given 3D coordinates around the x axis. */
|
||||
static void IsometricDrawer_RotateX(Real32 cosA, Real32 sinA);
|
||||
|
||||
/* Rotates the given 3D coordinates around the y axis. */
|
||||
static void IsometricDrawer_RotateY(Real32 cosA, Real32 sinA);
|
||||
|
||||
#endif
|
@ -29,10 +29,10 @@ Int32 Atlas1D_TexIdsCount;
|
||||
TextureRec Atlas1D_TexRec(TextureLoc texLoc, Int32 uCount, Int32* index);
|
||||
|
||||
/* Returns the index of the 1D atlas within the array of 1D atlases that contains the given texture id.*/
|
||||
#define Atlas1D_Index(texId) (texId) / Atlas1D_ElementsPerAtlas
|
||||
#define Atlas1D_Index(texLoc) ((texLoc) / Atlas1D_ElementsPerAtlas)
|
||||
|
||||
/* Returns the index of the given texture id within a 1D atlas. */
|
||||
#define Atlas1D_RowId(texId) (texId) % Atlas1D_ElementsPerAtlas
|
||||
#define Atlas1D_RowId(texLoc) ((texLoc) % Atlas1D_ElementsPerAtlas)
|
||||
|
||||
/* Updates variables and native textures for the 1D atlas array. */
|
||||
void Atlas1D_UpdateState(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user