mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-12 17:17:09 -04:00
PS1: Use a little bit less memory
This commit is contained in:
parent
95a1efe5f1
commit
5fb4887191
@ -12,7 +12,12 @@
|
||||
#include "Options.h"
|
||||
#include "Logger.h"
|
||||
|
||||
#define LIQUID_ANIM_MAX 64
|
||||
#ifdef CC_BUILD_LOWMEM
|
||||
#define LIQUID_ANIM_MAX 16
|
||||
#else
|
||||
#define LIQUID_ANIM_MAX 64
|
||||
#endif
|
||||
|
||||
#define WATER_TEX_LOC 14
|
||||
#define LAVA_TEX_LOC 30
|
||||
static void Animations_Update(int loc, struct Bitmap* bmp, int stride);
|
||||
@ -292,20 +297,20 @@ static void Animations_Clear(void) {
|
||||
}
|
||||
|
||||
static void Animations_Validate(void) {
|
||||
struct AnimationData data;
|
||||
struct AnimationData* data;
|
||||
int maxX, maxY, tileX, tileY;
|
||||
int i, j;
|
||||
|
||||
anims_validated = true;
|
||||
for (i = 0; i < anims_count; i++) {
|
||||
data = anims_list[i];
|
||||
data = &anims_list[i];
|
||||
|
||||
maxX = data.frameX + data.frameSize * data.statesCount;
|
||||
maxY = data.frameY + data.frameSize;
|
||||
tileX = Atlas2D_TileX(data.texLoc);
|
||||
tileY = Atlas2D_TileY(data.texLoc);
|
||||
maxX = data->frameX + data->frameSize * data->statesCount;
|
||||
maxY = data->frameY + data->frameSize;
|
||||
tileX = Atlas2D_TileX(data->texLoc);
|
||||
tileY = Atlas2D_TileY(data->texLoc);
|
||||
|
||||
if (data.frameSize > Atlas2D.TileSize || tileY >= Atlas2D.RowsCount) {
|
||||
if (data->frameSize > Atlas2D.TileSize || tileY >= Atlas2D.RowsCount) {
|
||||
Chat_Add2("&cAnimation frames for tile (%i, %i) are bigger than the size of a tile in terrain.png", &tileX, &tileY);
|
||||
} else if (maxX > anims_bmp.width || maxY > anims_bmp.height) {
|
||||
Chat_Add2("&cSome of the animation frames for tile (%i, %i) are at coordinates outside animations.png", &tileX, &tileY);
|
||||
@ -313,8 +318,8 @@ static void Animations_Validate(void) {
|
||||
/* if user has water/lava animations in their default.zip, disable built-in */
|
||||
/* However, 'usewateranim' and 'uselavaanim' files should always disable use */
|
||||
/* of custom water/lava animations, even when they exist in animations.png */
|
||||
if (data.texLoc == LAVA_TEX_LOC && !alwaysLavaAnim) useLavaAnim = false;
|
||||
if (data.texLoc == WATER_TEX_LOC && !alwaysWaterAnim) useWaterAnim = false;
|
||||
if (data->texLoc == LAVA_TEX_LOC && !alwaysLavaAnim) useLavaAnim = false;
|
||||
if (data->texLoc == WATER_TEX_LOC && !alwaysWaterAnim) useWaterAnim = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ static void UpdateFogMinimal(float fogDensity) {
|
||||
/* Exp fog mode: f = e^(-density*coord) */
|
||||
/* Solve coord for f = 0.05 (good approx for fog end) */
|
||||
/* i.e. log(0.05) = -density * coord */
|
||||
#define LOG_005 -2.99573227355399
|
||||
#define LOG_005 -2.99573227355399f
|
||||
|
||||
dist = (int)(LOG_005 / -fogDensity);
|
||||
Game_SetViewDistance(min(dist, Game_UserViewDistance));
|
||||
@ -83,7 +83,7 @@ static void UpdateFogMinimal(float fogDensity) {
|
||||
}
|
||||
|
||||
static void UpdateFogNormal(float fogDensity, PackedCol fogColor) {
|
||||
double density;
|
||||
float density;
|
||||
|
||||
if (fogDensity != 0.0f) {
|
||||
Gfx_SetFogMode(FOG_EXP);
|
||||
@ -96,10 +96,10 @@ static void UpdateFogNormal(float fogDensity, PackedCol fogColor) {
|
||||
0.99=z/end --> z=end*0.99
|
||||
therefore
|
||||
d = -ln(0.01)/(end*0.99) */
|
||||
#define LOG_001 -4.60517018598809
|
||||
#define LOG_001 -4.60517018598809f
|
||||
|
||||
density = -(LOG_001) / (Game_ViewDistance * 0.99);
|
||||
Gfx_SetFogDensity((float)density);
|
||||
density = -LOG_001 / (Game_ViewDistance * 0.99f);
|
||||
Gfx_SetFogDensity(density);
|
||||
} else {
|
||||
Gfx_SetFogMode(FOG_LINEAR);
|
||||
Gfx_SetFogEnd((float)Game_ViewDistance);
|
||||
|
@ -94,7 +94,7 @@ cc_bool Math_IsPowOf2(int value) {
|
||||
#define RND_MASK ((1ULL << 48) - 1)
|
||||
|
||||
void Random_SeedFromCurrentTime(RNGState* rnd) {
|
||||
TimeMS now = DateTime_CurrentUTC_MS();
|
||||
cc_uint64 now = Stopwatch_Measure();
|
||||
Random_Seed(rnd, (int)now);
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ extern cc_string Game_Mppass;
|
||||
|
||||
#if defined CC_BUILD_N64
|
||||
#define DEFAULT_VIEWDIST 20
|
||||
#elif defined CC_BUILD_NDS
|
||||
#elif defined CC_BUILD_NDS || defined CC_BUILD_PS1
|
||||
#define DEFAULT_VIEWDIST 192
|
||||
#else
|
||||
#define DEFAULT_VIEWDIST 512
|
||||
|
@ -543,4 +543,4 @@ void Gfx_EndFrame(void) {
|
||||
void Gfx_OnWindowResize(void) {
|
||||
glViewport(0, 0, Game.Width, Game.Height);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
274
src/Particle.c
274
src/Particle.c
@ -187,6 +187,30 @@ static void Rain_Tick(double delta) {
|
||||
}
|
||||
}
|
||||
|
||||
void Particles_RainSnowEffect(float x, float y, float z) {
|
||||
struct Particle* p;
|
||||
int i, type;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (rain_count == PARTICLES_MAX) Rain_RemoveAt(0);
|
||||
p = &rain_Particles[rain_count++];
|
||||
|
||||
p->velocity.x = Random_Float(&rnd) * 0.8f - 0.4f; /* [-0.4, 0.4] */
|
||||
p->velocity.z = Random_Float(&rnd) * 0.8f - 0.4f;
|
||||
p->velocity.y = Random_Float(&rnd) + 0.4f;
|
||||
|
||||
p->lastPos.x = x + Random_Float(&rnd); /* [0.0, 1.0] */
|
||||
p->lastPos.y = y + Random_Float(&rnd) * 0.1f + 0.01f;
|
||||
p->lastPos.z = z + Random_Float(&rnd);
|
||||
|
||||
p->nextPos = p->lastPos;
|
||||
p->lifetime = 40.0f;
|
||||
|
||||
type = Random_Next(&rnd, 30);
|
||||
p->size = type >= 28 ? 2 : (type >= 25 ? 4 : 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------Terrain particle---------------------------------------------------*
|
||||
@ -291,9 +315,92 @@ static void Terrain_Tick(double delta) {
|
||||
}
|
||||
}
|
||||
|
||||
void Particles_BreakBlockEffect(IVec3 coords, BlockID old, BlockID now) {
|
||||
struct TerrainParticle* p;
|
||||
TextureLoc loc;
|
||||
int texIndex;
|
||||
TextureRec baseRec, rec;
|
||||
Vec3 origin, minBB, maxBB;
|
||||
|
||||
/* texture UV variables */
|
||||
float uScale, vScale, maxU2, maxV2;
|
||||
int minX, minZ, maxX, maxZ;
|
||||
int minU, minV, maxU, maxV;
|
||||
int maxUsedU, maxUsedV;
|
||||
|
||||
/* per-particle variables */
|
||||
float cellX, cellY, cellZ;
|
||||
Vec3 cell;
|
||||
int x, y, z, type;
|
||||
|
||||
if (now != BLOCK_AIR || Blocks.Draw[old] == DRAW_GAS) return;
|
||||
IVec3_ToVec3(&origin, &coords);
|
||||
loc = Block_Tex(old, FACE_XMIN);
|
||||
|
||||
baseRec = Atlas1D_TexRec(loc, 1, &texIndex);
|
||||
uScale = (1.0f/16.0f); vScale = (1.0f/16.0f) * Atlas1D.InvTileSize;
|
||||
|
||||
minBB = Blocks.MinBB[old]; maxBB = Blocks.MaxBB[old];
|
||||
minX = (int)(minBB.x * 16); maxX = (int)(maxBB.x * 16);
|
||||
minZ = (int)(minBB.z * 16); maxZ = (int)(maxBB.z * 16);
|
||||
|
||||
minU = min(minX, minZ); minV = (int)(16 - maxBB.y * 16);
|
||||
maxU = min(maxX, maxZ); maxV = (int)(16 - minBB.y * 16);
|
||||
/* This way we can avoid creating particles which outside the bounds and need to be clamped */
|
||||
maxUsedU = maxU; maxUsedV = maxV;
|
||||
if (minU < 12 && maxU > 12) maxUsedU = 12;
|
||||
if (minV < 12 && maxV > 12) maxUsedV = 12;
|
||||
|
||||
#define GRID_SIZE 4
|
||||
/* gridOffset gives the centre of the cell on a grid */
|
||||
#define CELL_CENTRE ((1.0f / GRID_SIZE) * 0.5f)
|
||||
|
||||
maxU2 = baseRec.U1 + maxU * uScale;
|
||||
maxV2 = baseRec.V1 + maxV * vScale;
|
||||
for (x = 0; x < GRID_SIZE; x++) {
|
||||
for (y = 0; y < GRID_SIZE; y++) {
|
||||
for (z = 0; z < GRID_SIZE; z++) {
|
||||
|
||||
cellX = (float)x / GRID_SIZE; cellY = (float)y / GRID_SIZE; cellZ = (float)z / GRID_SIZE;
|
||||
cell = Vec3_Create3(CELL_CENTRE + cellX, CELL_CENTRE / 2 + cellY, CELL_CENTRE + cellZ);
|
||||
if (cell.x < minBB.x || cell.x > maxBB.x || cell.y < minBB.y
|
||||
|| cell.y > maxBB.y || cell.z < minBB.z || cell.z > maxBB.z) continue;
|
||||
|
||||
if (terrain_count == PARTICLES_MAX) Terrain_RemoveAt(0);
|
||||
p = &terrain_particles[terrain_count++];
|
||||
|
||||
/* centre random offset around [-0.2, 0.2] */
|
||||
p->base.velocity.x = CELL_CENTRE + (cellX - 0.5f) + (Random_Float(&rnd) * 0.4f - 0.2f);
|
||||
p->base.velocity.y = CELL_CENTRE + (cellY - 0.0f) + (Random_Float(&rnd) * 0.4f - 0.2f);
|
||||
p->base.velocity.z = CELL_CENTRE + (cellZ - 0.5f) + (Random_Float(&rnd) * 0.4f - 0.2f);
|
||||
|
||||
rec = baseRec;
|
||||
rec.U1 = baseRec.U1 + Random_Range(&rnd, minU, maxUsedU) * uScale;
|
||||
rec.V1 = baseRec.V1 + Random_Range(&rnd, minV, maxUsedV) * vScale;
|
||||
rec.U2 = rec.U1 + 4 * uScale;
|
||||
rec.V2 = rec.V1 + 4 * vScale;
|
||||
rec.U2 = min(rec.U2, maxU2) - 0.01f * uScale;
|
||||
rec.V2 = min(rec.V2, maxV2) - 0.01f * vScale;
|
||||
|
||||
Vec3_Add(&p->base.lastPos, &origin, &cell);
|
||||
p->base.nextPos = p->base.lastPos;
|
||||
p->base.lifetime = 0.3f + Random_Float(&rnd) * 1.2f;
|
||||
|
||||
p->rec = rec;
|
||||
p->texLoc = loc;
|
||||
p->block = old;
|
||||
type = Random_Next(&rnd, 30);
|
||||
p->base.size = type >= 28 ? 12 : (type >= 25 ? 10 : 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-------------------------------------------------------Custom particle---------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
#ifdef CC_BUILD_NETWORKING
|
||||
struct CustomParticle {
|
||||
struct Particle base;
|
||||
int effectId;
|
||||
@ -388,139 +495,6 @@ static void Custom_Tick(double delta) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*--------------------------------------------------------Particles--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
void Particles_Render(float t) {
|
||||
if (!terrain_count && !rain_count && !custom_count) return;
|
||||
|
||||
if (Gfx.LostContext) return;
|
||||
if (!particles_VB)
|
||||
particles_VB = Gfx_CreateDynamicVb(VERTEX_FORMAT_TEXTURED, PARTICLES_MAX * 4);
|
||||
|
||||
Gfx_SetAlphaTest(true);
|
||||
|
||||
Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED);
|
||||
Terrain_Render(t);
|
||||
Rain_Render(t);
|
||||
Custom_Render(t);
|
||||
|
||||
Gfx_SetAlphaTest(false);
|
||||
}
|
||||
|
||||
static void Particles_Tick(struct ScheduledTask* task) {
|
||||
double delta = task->interval;
|
||||
Terrain_Tick(delta);
|
||||
Rain_Tick(delta);
|
||||
Custom_Tick(delta);
|
||||
}
|
||||
|
||||
void Particles_BreakBlockEffect(IVec3 coords, BlockID old, BlockID now) {
|
||||
struct TerrainParticle* p;
|
||||
TextureLoc loc;
|
||||
int texIndex;
|
||||
TextureRec baseRec, rec;
|
||||
Vec3 origin, minBB, maxBB;
|
||||
|
||||
/* texture UV variables */
|
||||
float uScale, vScale, maxU2, maxV2;
|
||||
int minX, minZ, maxX, maxZ;
|
||||
int minU, minV, maxU, maxV;
|
||||
int maxUsedU, maxUsedV;
|
||||
|
||||
/* per-particle variables */
|
||||
float cellX, cellY, cellZ;
|
||||
Vec3 cell;
|
||||
int x, y, z, type;
|
||||
|
||||
if (now != BLOCK_AIR || Blocks.Draw[old] == DRAW_GAS) return;
|
||||
IVec3_ToVec3(&origin, &coords);
|
||||
loc = Block_Tex(old, FACE_XMIN);
|
||||
|
||||
baseRec = Atlas1D_TexRec(loc, 1, &texIndex);
|
||||
uScale = (1.0f/16.0f); vScale = (1.0f/16.0f) * Atlas1D.InvTileSize;
|
||||
|
||||
minBB = Blocks.MinBB[old]; maxBB = Blocks.MaxBB[old];
|
||||
minX = (int)(minBB.x * 16); maxX = (int)(maxBB.x * 16);
|
||||
minZ = (int)(minBB.z * 16); maxZ = (int)(maxBB.z * 16);
|
||||
|
||||
minU = min(minX, minZ); minV = (int)(16 - maxBB.y * 16);
|
||||
maxU = min(maxX, maxZ); maxV = (int)(16 - minBB.y * 16);
|
||||
/* This way we can avoid creating particles which outside the bounds and need to be clamped */
|
||||
maxUsedU = maxU; maxUsedV = maxV;
|
||||
if (minU < 12 && maxU > 12) maxUsedU = 12;
|
||||
if (minV < 12 && maxV > 12) maxUsedV = 12;
|
||||
|
||||
#define GRID_SIZE 4
|
||||
/* gridOffset gives the centre of the cell on a grid */
|
||||
#define CELL_CENTRE ((1.0f / GRID_SIZE) * 0.5f)
|
||||
|
||||
maxU2 = baseRec.U1 + maxU * uScale;
|
||||
maxV2 = baseRec.V1 + maxV * vScale;
|
||||
for (x = 0; x < GRID_SIZE; x++) {
|
||||
for (y = 0; y < GRID_SIZE; y++) {
|
||||
for (z = 0; z < GRID_SIZE; z++) {
|
||||
|
||||
cellX = (float)x / GRID_SIZE; cellY = (float)y / GRID_SIZE; cellZ = (float)z / GRID_SIZE;
|
||||
cell = Vec3_Create3(CELL_CENTRE + cellX, CELL_CENTRE / 2 + cellY, CELL_CENTRE + cellZ);
|
||||
if (cell.x < minBB.x || cell.x > maxBB.x || cell.y < minBB.y
|
||||
|| cell.y > maxBB.y || cell.z < minBB.z || cell.z > maxBB.z) continue;
|
||||
|
||||
if (terrain_count == PARTICLES_MAX) Terrain_RemoveAt(0);
|
||||
p = &terrain_particles[terrain_count++];
|
||||
|
||||
/* centre random offset around [-0.2, 0.2] */
|
||||
p->base.velocity.x = CELL_CENTRE + (cellX - 0.5f) + (Random_Float(&rnd) * 0.4f - 0.2f);
|
||||
p->base.velocity.y = CELL_CENTRE + (cellY - 0.0f) + (Random_Float(&rnd) * 0.4f - 0.2f);
|
||||
p->base.velocity.z = CELL_CENTRE + (cellZ - 0.5f) + (Random_Float(&rnd) * 0.4f - 0.2f);
|
||||
|
||||
rec = baseRec;
|
||||
rec.U1 = baseRec.U1 + Random_Range(&rnd, minU, maxUsedU) * uScale;
|
||||
rec.V1 = baseRec.V1 + Random_Range(&rnd, minV, maxUsedV) * vScale;
|
||||
rec.U2 = rec.U1 + 4 * uScale;
|
||||
rec.V2 = rec.V1 + 4 * vScale;
|
||||
rec.U2 = min(rec.U2, maxU2) - 0.01f * uScale;
|
||||
rec.V2 = min(rec.V2, maxV2) - 0.01f * vScale;
|
||||
|
||||
Vec3_Add(&p->base.lastPos, &origin, &cell);
|
||||
p->base.nextPos = p->base.lastPos;
|
||||
p->base.lifetime = 0.3f + Random_Float(&rnd) * 1.2f;
|
||||
|
||||
p->rec = rec;
|
||||
p->texLoc = loc;
|
||||
p->block = old;
|
||||
type = Random_Next(&rnd, 30);
|
||||
p->base.size = type >= 28 ? 12 : (type >= 25 ? 10 : 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Particles_RainSnowEffect(float x, float y, float z) {
|
||||
struct Particle* p;
|
||||
int i, type;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (rain_count == PARTICLES_MAX) Rain_RemoveAt(0);
|
||||
p = &rain_Particles[rain_count++];
|
||||
|
||||
p->velocity.x = Random_Float(&rnd) * 0.8f - 0.4f; /* [-0.4, 0.4] */
|
||||
p->velocity.z = Random_Float(&rnd) * 0.8f - 0.4f;
|
||||
p->velocity.y = Random_Float(&rnd) + 0.4f;
|
||||
|
||||
p->lastPos.x = x + Random_Float(&rnd); /* [0.0, 1.0] */
|
||||
p->lastPos.y = y + Random_Float(&rnd) * 0.1f + 0.01f;
|
||||
p->lastPos.z = z + Random_Float(&rnd);
|
||||
|
||||
p->nextPos = p->lastPos;
|
||||
p->lifetime = 40.0f;
|
||||
|
||||
type = Random_Next(&rnd, 30);
|
||||
p->size = type >= 28 ? 2 : (type >= 25 ? 4 : 3);
|
||||
}
|
||||
}
|
||||
|
||||
void Particles_CustomEffect(int effectID, float x, float y, float z, float originX, float originY, float originZ) {
|
||||
struct CustomParticle* p;
|
||||
struct CustomParticleEffect* e = &Particles_CustomEffects[effectID];
|
||||
@ -568,6 +542,40 @@ void Particles_CustomEffect(int effectID, float x, float y, float z, float origi
|
||||
if (IntersectsBlock(&p->base, CustomParticle_CanPass)) custom_count--;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static int custom_count;
|
||||
|
||||
static void Custom_Render(float t) { }
|
||||
static void Custom_Tick(double delta) { }
|
||||
#endif
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*--------------------------------------------------------Particles--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
void Particles_Render(float t) {
|
||||
if (!terrain_count && !rain_count && !custom_count) return;
|
||||
|
||||
if (Gfx.LostContext) return;
|
||||
if (!particles_VB)
|
||||
particles_VB = Gfx_CreateDynamicVb(VERTEX_FORMAT_TEXTURED, PARTICLES_MAX * 4);
|
||||
|
||||
Gfx_SetAlphaTest(true);
|
||||
|
||||
Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED);
|
||||
Terrain_Render(t);
|
||||
Rain_Render(t);
|
||||
Custom_Render(t);
|
||||
|
||||
Gfx_SetAlphaTest(false);
|
||||
}
|
||||
|
||||
static void Particles_Tick(struct ScheduledTask* task) {
|
||||
double delta = task->interval;
|
||||
Terrain_Tick(delta);
|
||||
Rain_Tick(delta);
|
||||
Custom_Tick(delta);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
|
@ -20,9 +20,9 @@ extern struct IGameComponent Textures_Component;
|
||||
#define ATLAS2D_SHIFT 4
|
||||
/* Maximum supported number of rows in the atlas. */
|
||||
#ifdef EXTENDED_TEXTURES
|
||||
#define ATLAS2D_MAX_ROWS_COUNT 32
|
||||
#define ATLAS2D_MAX_ROWS_COUNT 32
|
||||
#else
|
||||
#define ATLAS2D_MAX_ROWS_COUNT 16
|
||||
#define ATLAS2D_MAX_ROWS_COUNT 16
|
||||
#endif
|
||||
/* Maximum possible number of 1D terrain atlases. (worst case, each 1D atlas only has 1 tile) */
|
||||
#define ATLAS1D_MAX_ATLASES (ATLAS2D_TILES_PER_ROW * ATLAS2D_MAX_ROWS_COUNT)
|
||||
|
Loading…
x
Reference in New Issue
Block a user