Separate Simulation members required for rendering

More precisely, move them to RenderableSimulation, which Simulation now inherits from. This type is copyable and so is easy to send off to be rendered, potentially on a different thread.
This commit is contained in:
Tamás Bálint Misius 2024-07-06 09:11:53 +02:00
parent d24a70d6d1
commit c1a072f2e5
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2
20 changed files with 177 additions and 187 deletions

View File

@ -864,10 +864,10 @@ void Renderer::draw_air()
if(!(display_mode & DISPLAY_AIR))
return;
int x, y, i, j;
float (*pv)[XCELLS] = sim->air->pv;
float (*hv)[XCELLS] = sim->air->hv;
float (*vx)[XCELLS] = sim->air->vx;
float (*vy)[XCELLS] = sim->air->vy;
auto *pv = sim->pv;
auto *hv = sim->hv;
auto *vx = sim->vx;
auto *vy = sim->vy;
auto c = 0x000000_rgb;
for (y=0; y<YCELLS; y++)
for (x=0; x<XCELLS; x++)

View File

@ -12,14 +12,14 @@
#include <vector>
class RenderPreset;
class Simulation;
struct RenderableSimulation;
class Renderer;
struct Particle;
struct GraphicsFuncContext
{
const Renderer *ren;
const Simulation *sim;
const RenderableSimulation *sim;
RNG rng;
const Particle *pipeSubcallCpart;
Particle *pipeSubcallTpart;
@ -56,7 +56,7 @@ public:
RNG rng;
const Simulation *sim;
const RenderableSimulation *sim;
std::vector<unsigned int> render_modes;
unsigned int render_mode;
@ -142,7 +142,7 @@ public:
static std::unique_ptr<VideoBuffer> WallIcon(int wallID, Vec2<int> size);
Renderer(Simulation *newSim);
Renderer(RenderableSimulation *newSim);
#define RENDERER_TABLE(name) \
static std::vector<RGB<uint8_t>> name; \

View File

@ -221,7 +221,7 @@ void Renderer::PopulateTables()
}
}
Renderer::Renderer(Simulation *newSim):
Renderer::Renderer(RenderableSimulation *newSim):
sim(newSim),
render_mode(0),
colour_mode(0),

View File

@ -8,7 +8,7 @@
#include "graphics/Renderer.h"
#include "gui/Style.h"
#include "simulation/ElementDefs.h"
#include "simulation/SimulationData.h"
#include "simulation/SimulationSettings.h"
#include "client/Client.h"
#include "gui/dialogues/ConfirmPrompt.h"
#include "gui/dialogues/InformationMessage.h"

View File

@ -619,7 +619,7 @@ AnyType CommandInterface::tptS_reset(std::deque<String> * words)
for (int nx = 0; nx < XCELLS; nx++)
for (int ny = 0; ny < YCELLS; ny++)
{
sim->air->pv[ny][nx] = 0;
sim->pv[ny][nx] = 0;
}
}
else if (resetStr == "velocity")
@ -627,8 +627,8 @@ AnyType CommandInterface::tptS_reset(std::deque<String> * words)
for (int nx = 0; nx < XCELLS; nx++)
for (int ny = 0; ny < YCELLS; ny++)
{
sim->air->vx[ny][nx] = 0;
sim->air->vy[ny][nx] = 0;
sim->vx[ny][nx] = 0;
sim->vy[ny][nx] = 0;
}
}
else if (resetStr == "sparks")

View File

@ -900,7 +900,7 @@ static int resetPressure(lua_State *L)
for (int nx = x1; nx<x1+width; nx++)
for (int ny = y1; ny<y1+height; ny++)
{
lsi->sim->air->pv[ny][nx] = 0;
lsi->sim->pv[ny][nx] = 0;
}
return 0;
}

View File

@ -28,14 +28,14 @@ void Air::make_kernel(void) //used for velocity
void Air::Clear()
{
std::fill(&pv[0][0], &pv[0][0]+NCELL, 0.0f);
std::fill(&vy[0][0], &vy[0][0]+NCELL, 0.0f);
std::fill(&vx[0][0], &vx[0][0]+NCELL, 0.0f);
std::fill(&sim.pv[0][0], &sim.pv[0][0]+NCELL, 0.0f);
std::fill(&sim.vy[0][0], &sim.vy[0][0]+NCELL, 0.0f);
std::fill(&sim.vx[0][0], &sim.vx[0][0]+NCELL, 0.0f);
}
void Air::ClearAirH()
{
std::fill(&hv[0][0], &hv[0][0]+NCELL, ambientAirTemp);
std::fill(&sim.hv[0][0], &sim.hv[0][0]+NCELL, ambientAirTemp);
}
// Used when updating temp or velocity from far away
@ -43,6 +43,9 @@ const float advDistanceMult = 0.7f;
void Air::update_airh(void)
{
auto &vx = sim.vx;
auto &vy = sim.vy;
auto &hv = sim.hv;
for (auto i=0; i<YCELLS; i++) //sets air temp on the edges every frame
{
hv[i][0] = ambientAirTemp;
@ -169,6 +172,12 @@ void Air::update_airh(void)
void Air::update_air(void)
{
auto &vx = sim.vx;
auto &vy = sim.vy;
auto &pv = sim.pv;
auto &fvx = sim.fvx;
auto &fvy = sim.fvy;
auto &bmap = sim.bmap;
if (airMode != AIR_NOUPDATE) //airMode 4 is no air/pressure update
{
for (auto i=0; i<YCELLS; i++) //reduces pressure/velocity on the edges every frame
@ -390,6 +399,9 @@ void Air::update_air(void)
void Air::Invert()
{
auto &vx = sim.vx;
auto &vy = sim.vy;
auto &pv = sim.pv;
for (auto nx = 0; nx<XCELLS; nx++)
{
for (auto ny = 0; ny<YCELLS; ny++)
@ -440,14 +452,14 @@ Air::Air(Simulation & simulation):
{
//Simulation should do this.
make_kernel();
std::fill(&bmap_blockair[0][0], &bmap_blockair[0][0]+NCELL, 0);
std::fill(&bmap_blockairh[0][0], &bmap_blockairh[0][0]+NCELL, 0);
std::fill(&vx[0][0], &vx[0][0]+NCELL, 0.0f);
std::fill(&ovx[0][0], &ovx[0][0]+NCELL, 0.0f);
std::fill(&vy[0][0], &vy[0][0]+NCELL, 0.0f);
std::fill(&ovy[0][0], &ovy[0][0]+NCELL, 0.0f);
std::fill(&hv[0][0], &hv[0][0]+NCELL, 0.0f);
std::fill(&ohv[0][0], &ohv[0][0]+NCELL, 0.0f);
std::fill(&pv[0][0], &pv[0][0]+NCELL, 0.0f);
std::fill(&opv[0][0], &opv[0][0]+NCELL, 0.0f);
std::fill(&bmap_blockair [0][0], &bmap_blockair [0][0] + NCELL, 0);
std::fill(&bmap_blockairh[0][0], &bmap_blockairh[0][0] + NCELL, 0);
std::fill(&sim.vx[0][0], &sim.vx[0][0] + NCELL, 0.0f);
std::fill(&ovx [0][0], &ovx [0][0] + NCELL, 0.0f);
std::fill(&sim.vy[0][0], &sim.vy[0][0] + NCELL, 0.0f);
std::fill(&ovy [0][0], &ovy [0][0] + NCELL, 0.0f);
std::fill(&sim.hv[0][0], &sim.hv[0][0] + NCELL, 0.0f);
std::fill(&ohv [0][0], &ohv [0][0] + NCELL, 0.0f);
std::fill(&sim.pv[0][0], &sim.pv[0][0] + NCELL, 0.0f);
std::fill(&opv [0][0], &opv [0][0] + NCELL, 0.0f);
}

View File

@ -9,19 +9,9 @@ public:
Simulation & sim;
int airMode;
float ambientAirTemp;
//Arrays from the simulation
unsigned char (*bmap)[XCELLS];
unsigned char (*emap)[XCELLS];
float (*fvx)[XCELLS];
float (*fvy)[XCELLS];
//
float vx[YCELLS][XCELLS];
float ovx[YCELLS][XCELLS];
float vy[YCELLS][XCELLS];
float ovy[YCELLS][XCELLS];
float pv[YCELLS][XCELLS];
float opv[YCELLS][XCELLS];
float hv[YCELLS][XCELLS];
float ohv[YCELLS][XCELLS]; // Ambient Heat
unsigned char bmap_blockair[YCELLS][XCELLS];
unsigned char bmap_blockairh[YCELLS][XCELLS];

View File

@ -12,7 +12,7 @@ sign::sign(String text_, int x_, int y_, Justification justification_):
{
}
String sign::getDisplayText(const Simulation *sim, int &x0, int &y0, int &w, int &h, bool colorize, bool *v95) const
String sign::getDisplayText(const RenderableSimulation *sim, int &x0, int &y0, int &w, int &h, bool colorize, bool *v95) const
{
auto &sd = SimulationData::CRef();
String drawable_text;

View File

@ -2,7 +2,7 @@
#include "common/String.h"
#include <utility>
class Simulation;
struct RenderableSimulation;
struct sign
{
@ -29,6 +29,6 @@ struct sign
String text;
sign(String text_, int x_, int y_, Justification justification_);
String getDisplayText(const Simulation *sim, int &x, int &y, int &w, int &h, bool colorize = true, bool *v95 = nullptr) const;
String getDisplayText(const RenderableSimulation *sim, int &x, int &y, int &w, int &h, bool colorize = true, bool *v95 = nullptr) const;
std::pair<int, Type> split() const;
};

View File

@ -14,6 +14,7 @@
#include "elements/STKM.h"
#include "elements/PIPE.h"
#include "elements/FILT.h"
#include "elements/PRTI.h"
#include <iostream>
#include <set>
@ -3951,55 +3952,13 @@ void Simulation::AfterSim()
Simulation::~Simulation() = default;
Simulation::Simulation():
replaceModeSelected(0),
replaceModeFlags(0),
debug_nextToUpdate(0),
ISWIRE(0),
force_stacking_check(false),
emp_decor(0),
emp_trigger_count(0),
etrd_count_valid(false),
etrd_life0_count(0),
lightningRecreate(0),
gravWallChanged(false),
CGOL(0),
GSPEED(1),
edgeMode(EDGE_VOID),
gravityMode(GRAV_VERTICAL),
customGravityX(0),
customGravityY(0),
legacy_enable(0),
aheat_enable(0),
water_equal_test(0),
sys_pause(0),
framerender(0),
pretty_powder(0),
sandcolour_frame(0),
deco_space(DECOSPACE_SRGB)
Simulation::Simulation()
{
int tportal_rx[] = {-1, 0, 1, 1, 1, 0,-1,-1};
int tportal_ry[] = {-1,-1,-1, 0, 1, 1, 1, 0};
memcpy(portal_rx, tportal_rx, sizeof(tportal_rx));
memcpy(portal_ry, tportal_ry, sizeof(tportal_ry));
currentTick = 0;
std::fill(elementCount, elementCount+PT_NUM, 0);
elementRecount = true;
//Create and attach air simulation
air = std::make_unique<Air>(*this);
//Give air sim references to our data
air->bmap = bmap;
air->emap = emap;
air->fvx = fvx;
air->fvy = fvy;
//Air sim gives us maps to use
vx = air->vx;
vy = air->vy;
pv = air->pv;
hv = air->hv;
player.comm = 0;
player2.comm = 0;

View File

@ -11,6 +11,7 @@
#include "gravity/Gravity.h"
#include "Element.h"
#include "SimulationConfig.h"
#include "SimulationSettings.h"
#include <cstring>
#include <cstddef>
#include <vector>
@ -31,85 +32,96 @@ class Renderer;
class Air;
class GameSave;
class Simulation
struct RenderableSimulation
{
public:
GravityPtr grav;
GravityInput gravIn;
GravityOutput gravOut; // invariant: when grav is empty, this is in its default-constructed state
std::unique_ptr<Air> air;
RNG rng;
std::vector<sign> signs;
//Element * elements;
int currentTick;
int replaceModeSelected;
int replaceModeFlags;
int currentTick = 0;
int emp_decor = 0;
int debug_nextToUpdate;
int debug_mostRecentlyUpdated = -1; // -1 when between full update loops
int parts_lastActiveIndex;
int pfree;
int NUM_PARTS;
bool elementRecount;
int elementCount[PT_NUM];
int ISWIRE;
bool force_stacking_check;
int emp_decor;
int emp_trigger_count;
bool etrd_count_valid;
int etrd_life0_count;
int lightningRecreate;
//Stickman
playerst player;
playerst player2;
playerst fighters[MAX_FIGHTERS]; //Defined in Stickman.h
unsigned char fighcount; //Contains the number of fighters
bool gravWallChanged;
//Portals and Wifi
Particle portalp[CHANNELS][8][80];
int portal_rx[8];
int portal_ry[8];
int wireless[CHANNELS][2];
//Gol sim
int CGOL;
int GSPEED;
unsigned int gol[YRES][XRES][5];
//Air sim
float (*vx)[XCELLS];
float (*vy)[XCELLS];
float (*pv)[XCELLS];
float (*hv)[XCELLS];
//Walls
float vx[YCELLS][XCELLS];
float vy[YCELLS][XCELLS];
float pv[YCELLS][XCELLS];
float hv[YCELLS][XCELLS];
unsigned char bmap[YCELLS][XCELLS];
unsigned char emap[YCELLS][XCELLS];
float fvx[YCELLS][XCELLS];
float fvy[YCELLS][XCELLS];
//Particles
Particle parts[NPART];
int pmap[YRES][XRES];
int photons[YRES][XRES];
int aheat_enable = 0;
// initialized in clear_sim
int parts_lastActiveIndex;
bool useLuaCallbacks = false;
};
class Simulation : public RenderableSimulation
{
public:
GravityPtr grav;
std::unique_ptr<Air> air;
RNG rng;
int replaceModeSelected = 0;
int replaceModeFlags = 0;
int debug_nextToUpdate = 0;
int debug_mostRecentlyUpdated = -1; // -1 when between full update loops
int elementCount[PT_NUM];
int ISWIRE = 0;
bool force_stacking_check = false;
int emp_trigger_count = 0;
bool etrd_count_valid = false;
int etrd_life0_count = 0;
int lightningRecreate = 0;
bool gravWallChanged = false;
Particle portalp[CHANNELS][8][80];
int wireless[CHANNELS][2];
int CGOL = 0;
int GSPEED = 1;
unsigned int gol[YRES][XRES][5];
float fvx[YCELLS][XCELLS];
float fvy[YCELLS][XCELLS];
unsigned int pmap_count[YRES][XRES];
//Simulation Settings
int edgeMode;
int gravityMode;
float customGravityX;
float customGravityY;
int legacy_enable;
int aheat_enable;
int water_equal_test;
int sys_pause;
int framerender;
int pretty_powder;
int sandcolour;
int sandcolour_interface;
int sandcolour_frame;
int deco_space;
int edgeMode = EDGE_VOID;
int gravityMode = GRAV_VERTICAL;
float customGravityX = 0;
float customGravityY = 0;
int legacy_enable = 0;
int water_equal_test = 0;
int sys_pause = 0;
int framerender = 0;
int pretty_powder = 0;
int sandcolour_frame = 0;
int deco_space = DECOSPACE_SRGB;
// initialized in clear_sim
int pfree;
bool elementRecount;
unsigned char fighcount; //Contains the number of fighters
uint64_t frameCount;
bool ensureDeterminism;
// initialized very late >_>
int NUM_PARTS;
int sandcolour;
int sandcolour_interface;
void Load(const GameSave *save, bool includePressure, Vec2<int> blockP); // block coordinates
std::unique_ptr<GameSave> Save(bool includePressure, Rect<int> partR); // particle coordinates
void SaveSimOptions(GameSave &gameSave);
@ -211,8 +223,6 @@ public:
Simulation();
~Simulation();
bool useLuaCallbacks = false;
void EnableNewtonianGravity(bool enable);
void ResetNewtonianGravity(GravityInput newGravIn, GravityOutput newGravOut);
void DispatchNewtonianGravity();

View File

@ -141,30 +141,6 @@ constexpr int NGT_BRAN = 23;
constexpr auto REPLACE_MODE = UINT32_C(0x00000001);
constexpr auto SPECIFIC_DELETE = UINT32_C(0x00000002);
enum EdgeMode
{
EDGE_VOID, EDGE_SOLID, EDGE_LOOP, NUM_EDGEMODES
};
enum AirMode
{
AIR_ON, AIR_PRESSUREOFF, AIR_VELOCITYOFF, AIR_OFF, AIR_NOUPDATE, NUM_AIRMODES
};
enum GravityMode
{
GRAV_VERTICAL, GRAV_OFF, GRAV_RADIAL, GRAV_CUSTOM, NUM_GRAVMODES
};
enum DecoSpace
{
DECOSPACE_SRGB,
DECOSPACE_LINEAR,
DECOSPACE_GAMMA22,
DECOSPACE_GAMMA18,
NUM_DECOSPACES,
};
struct CustomGOLData
{
int rule, colour1, colour2;

View File

@ -0,0 +1,37 @@
#pragma once
enum EdgeMode
{
EDGE_VOID,
EDGE_SOLID,
EDGE_LOOP,
NUM_EDGEMODES,
};
enum AirMode
{
AIR_ON,
AIR_PRESSUREOFF,
AIR_VELOCITYOFF,
AIR_OFF,
AIR_NOUPDATE,
NUM_AIRMODES,
};
enum GravityMode
{
GRAV_VERTICAL,
GRAV_OFF,
GRAV_RADIAL,
GRAV_CUSTOM,
NUM_GRAVMODES,
};
enum DecoSpace
{
DECOSPACE_SRGB,
DECOSPACE_LINEAR,
DECOSPACE_GAMMA22,
DECOSPACE_GAMMA18,
NUM_DECOSPACES,
};

View File

@ -2,6 +2,7 @@
#include "simulation/orbitalparts.h"
#include "PIPE.h"
#include "SOAP.h"
#include "PRTI.h"
static int update(UPDATE_FUNC_ARGS);
static int graphics(GRAPHICS_FUNC_ARGS);
@ -72,8 +73,8 @@ static int update(UPDATE_FUNC_ARGS)
for (int count = 0; count < 8; count++)
{
int rx = sim->portal_rx[count];
int ry = sim->portal_ry[count];
int rx = portal_rx[count];
int ry = portal_ry[count];
if (rx || ry)
{
int r = pmap[y+ry][x+rx];

View File

@ -0,0 +1,4 @@
#pragma once
constexpr int portal_rx[8] = { -1, 0, 1, 1, 1, 0, -1, -1 };
constexpr int portal_ry[8] = { -1, -1, -1, 0, 1, 1, 1, 0 };

View File

@ -1,5 +1,6 @@
#include "simulation/ElementCommon.h"
#include "simulation/orbitalparts.h"
#include "PRTI.h"
static int update(UPDATE_FUNC_ARGS);
static int graphics(GRAPHICS_FUNC_ARGS);
@ -64,8 +65,8 @@ static int update(UPDATE_FUNC_ARGS)
else if (parts[i].tmp<0) parts[i].tmp = 0;
for (auto count=0; count<8; count++)
{
auto rx = sim->portal_rx[count];
auto ry = sim->portal_ry[count];
auto rx = portal_rx[count];
auto ry = portal_ry[count];
if (rx || ry)
{
auto r = pmap[y+ry][x+rx];

View File

@ -14,11 +14,11 @@ void SimTool::Tool_AIR()
static int perform(Simulation * sim, Particle * cpart, int x, int y, int brushX, int brushY, float strength)
{
sim->air->pv[y/CELL][x/CELL] += strength*0.05f;
sim->pv[y/CELL][x/CELL] += strength*0.05f;
if (sim->air->pv[y/CELL][x/CELL] > MAX_PRESSURE)
sim->air->pv[y/CELL][x/CELL] = MAX_PRESSURE;
else if (sim->air->pv[y/CELL][x/CELL] < MIN_PRESSURE)
sim->air->pv[y/CELL][x/CELL] = MIN_PRESSURE;
if (sim->pv[y/CELL][x/CELL] > MAX_PRESSURE)
sim->pv[y/CELL][x/CELL] = MAX_PRESSURE;
else if (sim->pv[y/CELL][x/CELL] < MIN_PRESSURE)
sim->pv[y/CELL][x/CELL] = MIN_PRESSURE;
return 1;
}

View File

@ -26,8 +26,8 @@ static int perform(Simulation * sim, Particle * cpart, int x, int y, int brushX,
if(brushX == x && brushY == y)
return 1;
float *vx = &sim->air->vx[y / CELL][x / CELL];
float *vy = &sim->air->vy[y / CELL][x / CELL];
float *vx = &sim->vx[y / CELL][x / CELL];
float *vy = &sim->vy[y / CELL][x / CELL];
auto dvx = float(brushX - x);
auto dvy = float(brushY - y);

View File

@ -14,11 +14,11 @@ void SimTool::Tool_VAC()
static int perform(Simulation * sim, Particle * cpart, int x, int y, int brushX, int brushY, float strength)
{
sim->air->pv[y/CELL][x/CELL] -= strength*0.05f;
sim->pv[y/CELL][x/CELL] -= strength*0.05f;
if (sim->air->pv[y/CELL][x/CELL] > MAX_PRESSURE)
sim->air->pv[y/CELL][x/CELL] = MAX_PRESSURE;
else if (sim->air->pv[y/CELL][x/CELL] < MIN_PRESSURE)
sim->air->pv[y/CELL][x/CELL] = MIN_PRESSURE;
if (sim->pv[y/CELL][x/CELL] > MAX_PRESSURE)
sim->pv[y/CELL][x/CELL] = MAX_PRESSURE;
else if (sim->pv[y/CELL][x/CELL] < MIN_PRESSURE)
sim->pv[y/CELL][x/CELL] = MIN_PRESSURE;
return 1;
}