Port IsometricBlockDrawer to C.

This commit is contained in:
UnknownShadow200 2017-06-07 10:53:26 +10:00
parent 5a60670ba1
commit 8e425763c7
7 changed files with 264 additions and 26 deletions

View File

@ -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;
}
}
}

View File

@ -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) {

View File

@ -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" />

View File

@ -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>

View 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;
}

View 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

View File

@ -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);