cool beans

This commit is contained in:
2025-11-23 00:25:45 +01:00
parent 2b410eee24
commit c300276c7d
5 changed files with 143 additions and 98 deletions

View File

@@ -220,13 +220,13 @@ uint64 factorial(int n) {
return result;
}
SomaSolutionList solve(VoxelSpaceReprList reprsInput, int dims[3]) {
Arena *arena = arenaAlloc(Megabytes(64));
SomaSolutionList solveSoma(Arena *solutionsArena, VoxelSpaceReprList reprsInput, int dims[3]) {
Arena *generalArena = arenaAlloc(Megabytes(64));
Arena *permsArena = arenaAlloc(Megabytes(128));
OffsetList offsets = PushList(arena, OffsetList, reprsInput.length + 1);
OffsetList offsets = PushList(generalArena, OffsetList, reprsInput.length + 1);
VoxelSpaceReprList polycubes = PushList(arena, VoxelSpaceReprList, 0);
VoxelSpaceReprList polycubes = PushList(generalArena, VoxelSpaceReprList, 0);
VoxelSpace emptyVoxelSpace = {
0,
@@ -245,7 +245,7 @@ SomaSolutionList solve(VoxelSpaceReprList reprsInput, int dims[3]) {
cullEmptySpace(&voxelSpace);
VoxelSpaceReprList positions = getAllPositionsInPrism(permsArena, &voxelSpace, dims);
possibleCombos += positions.length;
VoxelSpaceReprList_underlying *insertion = PushArray(arena, uint64, positions.capacity);
VoxelSpaceReprList_underlying *insertion = PushArray(generalArena, uint64, positions.capacity);
polycubes.capacity += positions.capacity;
polycubes.length += positions.length;
memcpy(insertion, positions.data, positions.capacity * ListElementSize(VoxelSpaceReprList));
@@ -258,7 +258,7 @@ SomaSolutionList solve(VoxelSpaceReprList reprsInput, int dims[3]) {
cullEmptySpace(&space);
VoxelSpaceReprList perms = getAllPermutationsInPrism(permsArena, &space, dims);
possibleCombos *= perms.length;
VoxelSpaceReprList_underlying *insertion = PushArray(arena, VoxelSpaceReprList_underlying, perms.capacity);
VoxelSpaceReprList_underlying *insertion = PushArray(generalArena, VoxelSpaceReprList_underlying, perms.capacity);
polycubes.capacity += perms.capacity;
polycubes.length += perms.length;
memcpy(insertion, perms.data, perms.capacity * ListElementSize(VoxelSpaceReprList));
@@ -277,14 +277,19 @@ SomaSolutionList solve(VoxelSpaceReprList reprsInput, int dims[3]) {
backtrackSolve(permsArena, &solver, 0, 0);
return filterUnique(permsArena, solver.solutions, dims);
SomaSolutionList uniqueSolns = filterUnique(solutionsArena, solver.solutions, dims);
arenaFree(permsArena);
arenaFree(generalArena);
return uniqueSolns;
}
void interactiveCmdLineSolveSoma() {
//get_dims_input(dims);
//std::cout << '\n';
//std::vector<uint64> reprs = get_reprs_input(dims[0]*dims[1]*dims[2]);
print("Great. Calculating solutions...\n");
SomaSolutionList solutions = solve(AsList(VoxelSpaceReprList, STD_SOMA), (int[]){ 3, 3, 3 });
print("%zu solutions found.\n", solutions.length);
//print("Great. Calculating solutions...\n");
//SomaSolutionList solutions = solveSoma(AsList(VoxelSpaceReprList, STD_SOMA), (int[]){ 3, 3, 3 });
//print("%zu solutions found.\n", solutions.length);
}

View File

@@ -5,5 +5,5 @@
typedef VoxelSpaceReprList SomaSolution;
DefineList(SomaSolution, SomaSolution);
SomaSolutionList solve(VoxelSpaceReprList reprs_in, int dims[3]);
void interactive_cmd_line_solve_soma();
SomaSolutionList solveSoma(Arena *solutionsArena, VoxelSpaceReprList reprs_in, int dims[3]);
void interactiveCmdLineSolveSoma();

View File

@@ -76,14 +76,6 @@ struct Frame {
Camera* cam;
};
typedef struct Polycube Polycube;
struct Polycube {
uint32 entityHandle;
VoxelSpace repr;
RLVector4 color;
};
DefineList(Polycube, Polycube);
DefineList(RLVector2, RLVec2);
DefineList(RLVector4, RLVec4);
DefineList(real32, Float);
@@ -154,60 +146,65 @@ typedef struct SomaState SomaState;
struct SomaState {
bool wireframe;
bool polycubeDirty;
uint32 currentPolycube;
uint32 lastPolycubeVisible;
uint32 displayedPolycube;
size_t displayedSolution;
bool displayingSolutions;
uint32 light;
PolycubeList polycubes;
Camera* camera;
RLVector3 rotAxisX;
RLVector3 rotAxisY;
PolycubeInputList polycubeInput;
Input input;
};
typedef struct Soma Soma;
struct Soma {
Scene *scene;
Renderer *renderer;
SomaState state;
Input currInput;
Input prevInput;
struct {
GLFWwindow *handle;
uint32 width;
uint32 height;
} window;
SomaState prevState;
SomaState state;
PolycubeInputList polycubeInput;
HandleList polycubes;
SomaSolutionList solutions;
HandleList solutionEntities;
};
void showEntity(Scene *scene, uint32 entityHandle) {
SceneGraphNode *node = getSceneGraphNodeForEntity(scene, entityHandle);
void show(Scene *s, uint32 graphNodeHandle) {
SceneGraphNode *node = getSceneGraphNode(s, graphNodeHandle);
if (node->entityHandle) {
getEntity(s, node->entityHandle)->flags |= EntityFlags_Visible;
}
for (EachIn(node->children, i)) {
uint32 child = node->children.data[i];
SceneGraphNode *subNode = getSceneGraphNode(scene, child);
if (subNode->entityHandle) {
getEntity(scene, subNode->entityHandle)->flags |= EntityFlags_Visible;
}
show(s, child);
}
}
void hideEntity(Scene *scene, uint32 entityHandle) {
SceneGraphNode *node = getSceneGraphNodeForEntity(scene, entityHandle);
void hide(Scene *s, uint32 graphNodeHandle) {
SceneGraphNode *node = getSceneGraphNode(s, graphNodeHandle);
if (node->entityHandle) {
getEntity(s, node->entityHandle)->flags &= ~EntityFlags_Visible;
}
for (EachIn(node->children, i)) {
uint32 child = node->children.data[i];
SceneGraphNode *subNode = getSceneGraphNode(scene, child);
if (subNode->entityHandle) {
getEntity(scene, subNode->entityHandle)->flags &= ~EntityFlags_Visible;
}
hide(s, child);
}
}
RLVector3 centreFromPolycube(Scene *scene, Polycube *p) {
RLVector3 centreFromPolycube(Scene *scene, uint32 p) {
RLVector3 centre = (RLVector3){0,0,0};
HandleList *children = &getSceneGraphNode(scene, p->entityHandle)->children;
HandleList *children = &getSceneGraphNode(scene, p)->children;
for (EachIn(*children, i)) {
uint32 child = children->data[i];
centre = Vector3Add(centre, getSceneGraphNode(scene, child)->translation);
}
centre = Vector3Scale(centre, 1.0f/(getSceneGraphNodeForEntity(scene, p->entityHandle)->children.length));
centre = Vector3Scale(centre, 1.0f/(getSceneGraphNode(scene, p)->children.length));
return centre;
}
@@ -328,8 +325,8 @@ Input getCurrentInput(GLFWwindow *window) {
}
void processInput(Soma *soma) {
Input *input = &soma->currInput;
Input *prevInput = &soma->prevInput;
Input *input = &soma->state.input;
Input *prevInput = &soma->prevState.input;
if (input->keyboard.escape) {
glfwSetWindowShouldClose(soma->window.handle, true);
@@ -347,39 +344,49 @@ void processInput(Soma *soma) {
node->translation.z += 1.0 * input->keyboard.z * shiftMultiplier;
if (input->keyboard.enter && !prevInput->keyboard.enter) {
if (soma->state.currentPolycube == 6) {
soma->state.currentPolycube = 0;
if (soma->state.displayingSolutions) {
if (soma->state.displayedSolution == soma->solutions.length - 1) {
soma->state.displayedSolution = 0;
} else {
soma->state.currentPolycube += 1;
soma->state.displayedSolution += 1;
}
} else {
if (soma->state.displayedPolycube == 6) {
soma->state.displayedPolycube = 0;
} else {
soma->state.displayedPolycube += 1;
}
}
}
bool dragScene = false;
if (input->mouse.btnLeft) {
Polycube *current_polycube = &soma->state.polycubes.data[soma->state.currentPolycube];
SceneGraphNode *polycubeGraphNode = getSceneGraphNodeForEntity(soma->scene, current_polycube->entityHandle);
uint32 currentObject = soma->state.displayingSolutions
? soma->solutionEntities.data[soma->state.displayedSolution]
: soma->polycubes.data[soma->state.displayedPolycube];
SceneGraphNode *objectGraphNode = getSceneGraphNode(soma->scene, currentObject);
real64 deltaX = (input->mouse.x - prevInput->mouse.x) * 0.005;
if (deltaX > 0.00000001 || deltaX < -0.00000001) {
polycubeGraphNode->rotation = QuaternionMultiply(polycubeGraphNode->rotation, QuaternionFromAxisAngle(soma->state.rotAxisY, -(real32)deltaX));
objectGraphNode->rotation = QuaternionMultiply(objectGraphNode->rotation, QuaternionFromAxisAngle(soma->state.rotAxisY, -(real32)deltaX));
}
real64 deltaY = (input->mouse.y - prevInput->mouse.y) * 0.005;
if (deltaY > 0.00000001 || deltaY < -0.00000001) {
polycubeGraphNode->rotation = QuaternionMultiply(QuaternionFromAxisAngle(soma->state.rotAxisX, -(real32)deltaY), polycubeGraphNode->rotation);
objectGraphNode->rotation = QuaternionMultiply(QuaternionFromAxisAngle(soma->state.rotAxisX, -(real32)deltaY), objectGraphNode->rotation);
}
}
}
Polycube createPolycubeFromRepr(Arena *arena, Scene *s, VoxelSpace *repr, RLVector4 color) {
uint32 polycubeMainEntityHandle = createEntity(arena, s);
Entity *polycubeMainEntity = getEntity(s, polycubeMainEntityHandle);
uint32 createPolycubeFromRepr(Arena *arena, Scene *s, VoxelSpace *repr, RLVector4 color) {
uint32 mainGraphNode = createSceneGraphNode(arena, s);
for (int x = 0; x < repr->dim_x; x++) {
for (int y = 0; y < repr->dim_y; y++) {
for (int z = 0; z < repr->dim_z; z++) {
if (filledAt(repr, x, y, z)) {
uint32 segmentEntityHandle = createEntity(arena, s);
Entity *polycubeSegment = getEntity(s, segmentEntityHandle);
polycubeSegment->color = color;
polycubeSegment->mesh = &cubeMesh;
polycubeSegment->tex = &wallTex;
SceneGraphNode *graphNode = getSceneGraphNode(s, polycubeSegment->graphNodeHandle);
@@ -388,19 +395,15 @@ Polycube createPolycubeFromRepr(Arena *arena, Scene *s, VoxelSpace *repr, RLVect
-((repr->dim_x - 1)/2.0f) + x,
((repr->dim_y - 1)/2.0f) - y
};
sceneNodeAddEntity(s, polycubeMainEntity->graphNodeHandle, segmentEntityHandle);
sceneNodeAddNode(s, mainGraphNode, polycubeSegment->graphNodeHandle);
}
}
}
}
Polycube result = {};
result.entityHandle = polycubeMainEntityHandle;
result.color = color;
result.repr = *repr;
SceneGraphNode *graphNode = getSceneGraphNodeForEntity(s, polycubeMainEntityHandle);
SceneGraphNode *graphNode = getSceneGraphNode(s, mainGraphNode);
graphNode->rotation = QuaternionMultiply(graphNode->rotation, QuaternionFromAxisAngle((RLVector3){1, 0, 0}, PI / 4));
graphNode->rotation = QuaternionMultiply(graphNode->rotation, QuaternionFromAxisAngle((RLVector3){0, 1, 0}, -PI / 4));
return result;
return mainGraphNode;
}
RenderObjects_Rectangle createRectangleObjects(Arena *arena, size_t count) {
@@ -491,7 +494,6 @@ Renderer createRenderer(Arena *arena, Scene *scene) {
result.scene = scene;
result.scene->sceneRoot = createSceneGraphNode(arena, scene);
result.rects = createRectangleObjects(arena, 100);
initGraphNode(getSceneGraphNode(scene, scene->sceneRoot));
return result;
}
@@ -517,15 +519,15 @@ void renderEnd(Soma *soma, Renderer *renderer) {
setUniform3fv(&phongShader, "light_pos", &lightGraphNode->translation);
setUniform3fv(&phongShader, "camera", &soma->state.camera->pos);
Polycube *currentPolycube = &soma->state.polycubes.data[soma->state.currentPolycube];
uint32 currentPolycube = soma->polycubes.data[soma->state.displayedPolycube];
glBindVertexArray(cubeMesh.vao);
setUniform4fv(&phongShader, "solid_color", &currentPolycube->color);
int model_uniform = getUniformLocation(&phongShader, "model");
for (EachIn(renderer->scene->entities, i)) {
Entity *entity = &renderer->scene->entities.data[i];
if (entity->flags & EntityFlags_Render && entity->flags & EntityFlags_Visible) {
setUniform4fv(&phongShader, "solid_color", &entity->color);
setUniformMat4fvByLoc(model_uniform, &getSceneGraphNode(renderer->scene, entity->graphNodeHandle)->world);
glBindTexture(GL_TEXTURE_2D, entity->tex->tex_id);
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)entity->mesh->num_indices);
@@ -587,7 +589,7 @@ bool ui_checkboxRect(UI_Context *ui, bool *value, UI_Rect rect) {
}
void uiPass(Soma *soma, UI_Context *ui, Renderer *renderer) {
PolycubeInput *currentPolycube = &soma->state.polycubeInput.data[soma->state.currentPolycube];
PolycubeInput *currentPolycube = &soma->polycubeInput.data[soma->state.displayedPolycube];
real32 boxSize = 30;
real32 padding = 20;
@@ -646,10 +648,12 @@ int mainGfx() {
GLFWcursor *pointerCursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
GLFWcursor *arrowCursor = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
soma.state.currentPolycube = 0;
soma.state.lastPolycubeVisible = 6;
soma.state.polycubeInput = PushListZero(arena, PolycubeInputList, 64);
soma.state.polycubes = PushListZero(arena, PolycubeList, 64);
soma.polycubeInput = PushListZero(arena, PolycubeInputList, 64);
soma.polycubes = PushListZero(arena, HandleList, 64);
soma.state.displayingSolutions = true;
soma.state.displayedPolycube = 0;
soma.state.displayedSolution = 0;
soma.state.light = createEntity(arena, &mainScene);
soma.state.camera = mainFrame.cam;
@@ -678,18 +682,38 @@ int mainGfx() {
VoxelSpace voxelSpace = { stdSoma.data[i], 3, 3, 3 };
RLVector4 color = colorFromIndex(i);
PolycubeInput input = (PolycubeInput){ voxelSpace, color };
AppendList(&soma.state.polycubeInput, input);
AppendList(&soma.polycubeInput, input);
cullEmptySpace(&voxelSpace);
Polycube polycube = createPolycubeFromRepr(arena, soma.scene, &voxelSpace, color);
polycube.color = color;
AppendList(&soma.state.polycubes, polycube);
sceneNodeAddEntity(renderer.scene, renderer.scene->sceneRoot, polycube.entityHandle);
uint32 polycubeGraphNodeHandle = createPolycubeFromRepr(arena, soma.scene, &voxelSpace, color);
AppendList(&soma.polycubes, polycubeGraphNodeHandle);
sceneNodeAddNode(renderer.scene, renderer.scene->sceneRoot, polycubeGraphNodeHandle);
}
soma.solutions = solveSoma(arena, AsList(VoxelSpaceReprList, STD_SOMA), (int[]){ 3, 3, 3 });
soma.solutionEntities = PushList(arena, HandleList, soma.solutions.length);
for (EachEl(soma.solutions, SomaSolution, solution)) {
uint32 solutionGraphNodeHandle = createSceneGraphNode(arena, soma.scene);
AppendList(&soma.solutionEntities, solutionGraphNodeHandle);
sceneNodeAddNode(renderer.scene, renderer.scene->sceneRoot, solutionGraphNodeHandle);
for (EachIn(*solution, soln_i)) {
uint32 polycubeGraphNodeHandle = createPolycubeFromRepr(
arena,
soma.scene,
&(VoxelSpace){ solution->data[soln_i], 3, 3, 3 },
colorFromIndex(soln_i)
);
sceneNodeAddNode(renderer.scene, solutionGraphNodeHandle, polycubeGraphNodeHandle);
}
}
show(soma.scene, soma.solutionEntities.data[soma.state.displayedSolution]);
print("%zu\n", soma.scene->entities.length);
print("%zu\n", soma.scene->graphNodes.length);
soma.state.camera->pos = (RLVector3){0.0f, 0.0f, 8.0f};
cameraLookAt(soma.state.camera, 0.0f, 0.0f, 0.0f);
SceneGraphNode *reference_polycube_gn = getSceneGraphNodeForEntity(soma.scene, soma.state.polycubes.data[0].entityHandle);
SceneGraphNode *reference_polycube_gn = getSceneGraphNode(soma.scene, soma.polycubes.data[0]);
Matrix worldInverse = MatrixInvert(reference_polycube_gn->world);
soma.state.rotAxisY = Vector3Normalize((RLVector3){worldInverse.m4, worldInverse.m5, worldInverse.m6});
RLVector3 eyes = Vector3Normalize(Vector3Subtract(soma.state.camera->pos, reference_polycube_gn->translation));
@@ -702,27 +726,35 @@ int mainGfx() {
real64 frameStart = glfwGetTime();
glfwPollEvents();
soma.currInput = getCurrentInput(soma.window.handle);
soma.state.input = getCurrentInput(soma.window.handle);
processInput(&soma);
/*
if (soma.state.lastPolycubeVisible != soma.state.currentPolycube) {
hideEntity(soma.scene, soma.state.polycubes.data[soma.state.lastPolycubeVisible].entityHandle);
showEntity(soma.scene, soma.state.polycubes.data[soma.state.currentPolycube].entityHandle);
hide(soma.scene, soma.state.polycubes.data[soma.state.lastPolycubeVisible].graphNodeHandle);
show(soma.scene, soma.state.polycubes.data[soma.state.currentPolycube].graphNodeHandle);
soma.state.lastPolycubeVisible = soma.state.currentPolycube;
}
*/
if (soma.state.displayedSolution != soma.prevState.displayedSolution) {
show(soma.scene, soma.solutionEntities.data[soma.state.displayedSolution]);
hide(soma.scene, soma.solutionEntities.data[soma.prevState.displayedSolution]);
}
if (soma.state.polycubeDirty) {
Polycube *currentPolycube = &soma.state.polycubes.data[soma.state.currentPolycube];
PolycubeInput *pinput = &soma.state.polycubeInput.data[soma.state.currentPolycube];
removeEntity(soma.scene, currentPolycube->entityHandle);
uint32 currentPolycube = soma.polycubes.data[soma.state.displayedPolycube];
PolycubeInput *pinput = &soma.polycubeInput.data[soma.state.displayedPolycube];
removeEntity(soma.scene, currentPolycube);
VoxelSpace culledRepr = pinput->repr;
cullEmptySpace(&culledRepr);
Polycube newPolycube = createPolycubeFromRepr(arena, soma.scene, &culledRepr, pinput->color);
SceneGraphNode *graphNode = getSceneGraphNodeForEntity(soma.scene, newPolycube.entityHandle);
graphNode->rotation = getSceneGraphNodeForEntity(soma.scene, currentPolycube->entityHandle)->rotation;
soma.state.polycubes.data[soma.state.currentPolycube] = newPolycube;
sceneNodeAddEntity(soma.scene, soma.scene->sceneRoot, newPolycube.entityHandle);
uint32 newPolycube = createPolycubeFromRepr(arena, soma.scene, &culledRepr, pinput->color);
SceneGraphNode *graphNode = getSceneGraphNode(soma.scene, newPolycube);
graphNode->rotation = getSceneGraphNode(soma.scene, currentPolycube)->rotation;
soma.polycubes.data[soma.state.displayedPolycube] = newPolycube;
sceneNodeAddNode(soma.scene, soma.scene->sceneRoot, newPolycube);
soma.state.polycubeDirty = false;
showEntity(soma.scene, newPolycube.entityHandle);
show(soma.scene, newPolycube);
}
updateViewportFromFrame(soma.window.width, soma.window.height, &mainFrame);
@@ -731,8 +763,8 @@ int mainGfx() {
renderBegin(&renderer);
ui.cursorIsPointer = false;
ui.prevInput = &soma.prevInput;
ui.input = &soma.currInput;
ui.prevInput = &soma.prevState.input;
ui.input = &soma.state.input;
ui.renderer = &renderer;
uiPass(&soma, &ui, &renderer);
if (ui.cursorIsPointer) {
@@ -750,7 +782,7 @@ int mainGfx() {
glfwSwapBuffers(soma.window.handle);
soma.prevInput = soma.currInput;
soma.prevState = soma.state;
}
glfwTerminate();
@@ -759,6 +791,6 @@ int mainGfx() {
int main() {
initialiseDjStdCore();
return mainCmd();
return mainGfx();
}

View File

@@ -15,7 +15,9 @@ SceneGraphNode *getSceneGraphNode(Scene *s, uint32 sceneGraphNodeHandle) {
uint32 createSceneGraphNode(Arena *arena, Scene *s) {
AppendList(&s->graphNodes, (SceneGraphNode){0});
s->graphNodes.data[s->graphNodes.length - 1].children = PushList(arena, HandleList, 64);
SceneGraphNode *node = &s->graphNodes.data[s->graphNodes.length - 1];
node->children = PushList(arena, HandleList, 1000);
initGraphNode(node);
return (uint32)s->graphNodes.length;
}
@@ -26,7 +28,6 @@ uint32 createEntity(Arena *arena, Scene *s) {
getSceneGraphNode(s, graphNodeId)->entityHandle = (uint32)s->entities.length;
uint32 handle = (uint32)s->entities.length;
uint32 graphNodeHandle = (uint32)s->graphNodes.length;
initGraphNode(getSceneGraphNode(s, graphNodeHandle));
return handle;
}
@@ -44,8 +45,8 @@ void recalcGraphNode(SceneGraphNode *n) {
Scene createScene(Arena *arena) {
Scene result = {};
result.entities = PushList(arena, EntityList, 1024);
result.graphNodes = PushList(arena, SceneGraphNodeList, 1024);
result.entities = PushList(arena, EntityList, 100000);
result.graphNodes = PushList(arena, SceneGraphNodeList, 100000);
result.sceneRoot = createSceneGraphNode(arena, &result);
return result;
}
@@ -90,3 +91,8 @@ void sceneNodeAddEntity(Scene *s, uint32 graphNodeHandle, uint32 entityHandle) {
HandleList *childList = &getSceneGraphNode(s, graphNodeHandle)->children;
AppendList(childList, getEntity(s, entityHandle)->graphNodeHandle);
}
void sceneNodeAddNode(Scene *s, uint32 recipientNodeHandle, uint32 graphNodeHandle) {
HandleList *childList = &getSceneGraphNode(s, recipientNodeHandle)->children;
AppendList(childList, graphNodeHandle);
}

View File

@@ -11,10 +11,11 @@ enum EntityFlags {
typedef struct Entity Entity;
struct Entity {
Mesh *mesh;
Texture *tex;
uint32 graphNodeHandle;
uint64 flags;
RLVector4 color;
Mesh *mesh;
Texture *tex;
};
DefineList(Entity, Entity);
@@ -48,5 +49,6 @@ void recalcGraphNode(SceneGraphNode *n);
void recalcSceneGraphNode(Scene *s, uint32 parentHandle);
void recalcScene(Scene *s);
void removeEntity(Scene *s, uint32 entityHandle);
void sceneNodeAddNode(Scene *s, uint32 recipientNodeHandle, uint32 graphNodeHandle);
void sceneNodeAddEntity(Scene *s, uint32 graphNodeHandle, uint32 entityHandle);
SceneGraphNode *getSceneGraphNodeForEntity(Scene *s, uint32 entityHandle);