This commit is contained in:
2026-02-01 22:29:58 +01:00
parent e25004f59c
commit e71ba138c0
8 changed files with 252 additions and 185 deletions

4
build
View File

@@ -10,6 +10,8 @@ else
time clang -O2 $COMMON_FLAGS ./src/main.c -o ./target/somaesque $LIB_INCLUDE
fi
echo [Target built]
if [ "$1" == "run" ]; then
./target/somaesque
fi

View File

@@ -139,7 +139,7 @@ void backtrackSolve(Arena *arena, Solver *solver, uint64 working_solution, size_
VoxelSpaceReprList last_soln_copy = PushList(arena, VoxelSpaceReprList, last_soln.length);
last_soln_copy.length = last_soln.length;
memcpy(last_soln_copy.data, last_soln.data, last_soln.length * ListElementSize(VoxelSpaceReprList));
AppendList(solutions, last_soln_copy);
ListAppend(*solutions, last_soln_copy);
return;
} else {
backtrackSolve(arena, solver, new_working_solution, curr_piece + 1);
@@ -165,7 +165,7 @@ SomaSolutionList getSolutionRotations(Arena *arena, SomaSolution *solution, int
};
VoxelSpaceList pieceRotations = getAllRotations(arena, &space);
for (EachIn(pieceRotations, rot_i)) {
AppendList(&result.data[rot_i], pieceRotations.data[rot_i].space);
ListAppend(result.data[rot_i], pieceRotations.data[rot_i].space);
}
}
return result;
@@ -204,7 +204,7 @@ SomaSolutionList filterUnique(Arena *arena, SomaSolutionList *solutions, int dim
solutionCopy.capacity = solution->length;
solutionCopy.length = solution->length;
memcpy(solutionCopy.data, solution->data, ListElementSize(SomaSolutionList) * solution->length);
AppendList(&uniqueSolns, solutionCopy);
ListAppend(uniqueSolns, solutionCopy);
}
}
return uniqueSolns;
@@ -233,7 +233,7 @@ SomaSolutionList solveSoma(Arena *solutionsArena, VoxelSpaceReprList reprsInput,
dims[2],
};
AppendList(&offsets, 0);
ListAppend(offsets, 0);
uint64 possibleCombos = 0;
@@ -250,7 +250,7 @@ SomaSolutionList solveSoma(Arena *solutionsArena, VoxelSpaceReprList reprsInput,
};
for (size_t i = 1; i < reprsInput.length; i++) {
AppendList(&offsets, polycubes.capacity);
ListAppend(offsets, polycubes.capacity);
VoxelSpace space = emptyVoxelSpace;
space.space = reprsInput.data[i];
cullEmptySpace(&space);
@@ -262,10 +262,10 @@ SomaSolutionList solveSoma(Arena *solutionsArena, VoxelSpaceReprList reprsInput,
memcpy(insertion, perms.data, perms.capacity * ListElementSize(VoxelSpaceReprList));
}
AppendList(&offsets, polycubes.length);
ListAppend(offsets, polycubes.length);
SomaSolutionList solutions = PushList(permsArena, SomaSolutionList, (size_t)floor(sqrt(possibleCombos)));
AppendList(&solutions, PushFullList(permsArena, SomaSolution, reprsInput.length));
ListAppend(solutions, PushFullList(permsArena, SomaSolution, reprsInput.length));
Solver solver = {
&polycubes,

View File

@@ -177,7 +177,7 @@ void pushNewUniqueSpins(VoxelSpaceList *existingSpaces, VoxelSpace* spaceToSpin)
}
}
if (!matchFound) {
AppendList(existingSpaces, spins[i]);
ListAppend(*existingSpaces, spins[i]);
}
}
}
@@ -186,7 +186,7 @@ void pushXAxisSpins(Arena *arena, VoxelSpaceList *existingSpaces, VoxelSpace* sp
VoxelSpace refSpace = *spaceToSpin;
for (int i = 0; i < 4; i++) {
rotate90X(&refSpace);
AppendList(existingSpaces, refSpace);
ListAppend(*existingSpaces, refSpace);
}
}

View File

@@ -217,7 +217,7 @@ struct Soma {
SomaSolutionList solutions;
SolveTaskCtx solveTaskCtx;
uint32 puzzleDims[3];
HandleList solutionEntities;
int32 solutionNode;
};
void *executeSolve(void *ctx) {
@@ -232,7 +232,7 @@ void *executeSolve(void *ctx) {
void scheduleSolve(Soma *soma) {
VoxelSpaceReprList mappedInputs = PushList(soma->solveTaskCtx.arena, VoxelSpaceReprList, soma->polycubeInput.length);
for (EachEl(soma->polycubeInput, PolycubeInput, polycubeInput)) {
AppendList(&mappedInputs, polycubeInput->repr.space);
ListAppend(mappedInputs, polycubeInput->repr.space);
}
soma->solveTaskCtx.input = mappedInputs;
soma->solveTaskCtx.taskStatus = SolveTaskStatus_Solving;
@@ -248,9 +248,10 @@ void show(Scene *s, uint32 graphNodeHandle) {
if (node->entityHandle) {
getEntity(s, node->entityHandle)->flags |= EntityFlags_Visible;
}
for (EachIn(node->children, i)) {
uint32 child = node->children.data[i];
show(s, child);
int32 next = node->firstChild;
while (next) {
show(s, next);
next = getSceneGraphNode(s, next)->nextSibling;
}
}
@@ -259,20 +260,24 @@ void hide(Scene *s, uint32 graphNodeHandle) {
if (node->entityHandle) {
getEntity(s, node->entityHandle)->flags &= ~EntityFlags_Visible;
}
for (EachIn(node->children, i)) {
uint32 child = node->children.data[i];
hide(s, child);
int32 next = node->firstChild;
while (next) {
hide(s, next);
next = getSceneGraphNode(s, next)->nextSibling;
}
}
RLVector3 centreFromPolycube(Scene *scene, uint32 p) {
RLVector3 centre = (RLVector3){0,0,0};
HandleList *children = &getSceneGraphNode(scene, p)->children;
for (EachIn(*children, i)) {
uint32 child = children->data[i];
centre = Vector3Add(centre, getSceneGraphNode(scene, child)->translation);
int32 childCount = 0;
int32 nextChild = getSceneGraphNode(scene, p)->firstChild;
while (nextChild) {
SceneGraphNode *node = getSceneGraphNode(scene, nextChild);
centre = Vector3Add(centre, node->translation);
nextChild = node->nextSibling;
childCount++;
}
centre = Vector3Scale(centre, 1.0f/(getSceneGraphNode(scene, p)->children.length));
centre = Vector3Scale(centre, 1.0f/childCount);
return centre;
}
@@ -411,7 +416,7 @@ void processInput(Soma *soma, UI_Context *ui) {
soma->state.displayedSolution += 1;
}
} else {
if (soma->state.displayedPolycube == 6) {
if (soma->state.displayedPolycube == soma->polycubeInput.length - 1) {
soma->state.displayedPolycube = 0;
} else {
soma->state.displayedPolycube += 1;
@@ -422,14 +427,15 @@ void processInput(Soma *soma, UI_Context *ui) {
if (input->keyboard.enter && !prevInput->keyboard.enter) {
if (soma->state.displayingSolutions) {
soma->state.displayingSolutions = false;
} else {
soma->state.displayedSolution = -1;
} else if (soma->solveTaskCtx.taskStatus == SolveTaskStatus_Ready) {
scheduleSolve(soma);
}
}
if (input->mouse.btnLeft && ui->hotNode == 0) {
uint32 currentObject = soma->state.displayingSolutions
? soma->solutionEntities.data[soma->state.displayedSolution]
? soma->solutionNode
: soma->polycubes.data[soma->state.displayedPolycube];
SceneGraphNode *objectGraphNode = getSceneGraphNode(soma->scene, currentObject);
@@ -456,7 +462,7 @@ uint32 createPolycubeFromRepr(Scene *s, VoxelSpace *repr, RLVector4 color) {
polycubeSegment->color = color;
polycubeSegment->mesh = &cubeMesh;
polycubeSegment->tex = &wallTex;
SceneGraphNode *graphNode = getSceneGraphNode(s, polycubeSegment->graphNodeHandle);
SceneGraphNode *graphNode = getSceneGraphNodeForEntity(s, segmentEntityHandle);
graphNode->translation = (RLVector3){
-((repr->dim_z - 1)/2.0f) + z,
-((repr->dim_x - 1)/2.0f) + x,
@@ -557,7 +563,6 @@ void updateRectangleObjectBuffers(Renderer *r) {
}
Renderer createRenderer(Arena *arena, Scene *scene) {
scene->sceneRoot = createSceneGraphNode(scene);
return (Renderer){
.scene = scene,
.rects = createRectangleObjects(arena, 1024),
@@ -615,12 +620,12 @@ void renderEnd(Soma *soma, Renderer *renderer) {
}
void rendererPlaceRectangle(Renderer *r, real32 x, real32 y, real32 width, real32 height, RLVector4 color, real32 borderRadius, real32 borderThickness) {
AppendList(&r->rects.p0, ((RLVector2){ x, y }));
AppendList(&r->rects.p1, ((RLVector2){ x + width, y + height }));
AppendList(&r->rects.color, color);
AppendList(&r->rects.borderRadius, borderRadius);
AppendList(&r->rects.borderThickness, borderThickness);
AppendList(&r->rects.edgeSoftness, 0.0f);
ListAppend(r->rects.p0, ((RLVector2){ x, y }));
ListAppend(r->rects.p1, ((RLVector2){ x + width, y + height }));
ListAppend(r->rects.color, color);
ListAppend(r->rects.borderRadius, borderRadius);
ListAppend(r->rects.borderThickness, borderThickness);
ListAppend(r->rects.edgeSoftness, 0.0f);
}
bool pointInRect(RLVector2 point, UI_Rect rect) {
@@ -729,68 +734,61 @@ void uiPass(Soma *soma, UI_Context *ui) {
}
void updatePolycubeDisplay(Arena *arena, Soma *soma) {
if (!soma->prevState.displayingSolutions && soma->state.displayingSolutions) {
if (soma->prevState.displayedPolycube < soma->polycubes.length) {
hide(soma->scene, soma->polycubes.data[soma->state.displayedPolycube]);
}
} else if (soma->prevState.displayingSolutions && !soma->state.displayingSolutions) {
if (soma->prevState.displayedSolution < soma->solutionEntities.length) {
hide(soma->scene, soma->solutionEntities.data[soma->state.displayedSolution]);
Scene *s = soma->scene;
if (soma->state.displayingSolutions && soma->state.displayedSolution != soma->prevState.displayedSolution) {
removeSceneGraphNode(s, soma->solutionNode);
if (soma->state.displayedSolution >= 0 && soma->state.displayedSolution < soma->solutions.length) {
SomaSolution soln = soma->solutions.data[soma->state.displayedSolution];
soma->solutionNode = createSceneGraphNode(s);
for (EachIn(soln, i)) {
uint32 polycubeGraphNodeHandle = createPolycubeFromRepr(
s,
&(VoxelSpace){ soln.data[i], 3, 3, 3 },
colorFromIndex(i)
);
sceneNodeAddNode(s, soma->solutionNode, polycubeGraphNodeHandle);
}
sceneNodeAddNode(s, s->sceneRoot, soma->solutionNode);
}
}
if (soma->state.displayingSolutions) {
if (soma->solutions.length > 0) {
show(soma->scene, soma->solutionEntities.data[soma->state.displayedSolution]);
if (soma->state.displayedSolution != soma->prevState.displayedSolution) {
hide(soma->scene, soma->solutionEntities.data[soma->prevState.displayedSolution]);
}
show(s, soma->solutionNode);
if (soma->prevState.displayedPolycube >= 0 && soma->prevState.displayedPolycube < soma->polycubes.length) {
hide(s, soma->polycubes.data[soma->prevState.displayedPolycube]);
}
} else {
if (soma->polycubes.length > 0) {
show(soma->scene, soma->polycubes.data[soma->state.displayedPolycube]);
if (soma->state.displayedPolycube != soma->prevState.displayedPolycube) {
hide(soma->scene, soma->polycubes.data[soma->prevState.displayedPolycube]);
hide(s, soma->solutionNode);
if (soma->state.displayedPolycube >= 0 && soma->state.displayedPolycube < soma->polycubes.length) {
show(s, soma->polycubes.data[soma->state.displayedPolycube]);
}
if (soma->state.displayedPolycube != soma->prevState.displayedPolycube) {
if (soma->prevState.displayedPolycube >= 0 && soma->prevState.displayedPolycube < soma->polycubes.length) {
hide(s, soma->polycubes.data[soma->prevState.displayedPolycube]);
}
}
}
if (soma->state.polycubeDirty) {
if (soma->state.displayedPolycube >= 0 && soma->state.displayedPolycube < soma->polycubes.length) {
uint32 currentPolycubeHandle = soma->polycubes.data[soma->state.displayedPolycube];
PolycubeInput *pinput = &soma->polycubeInput.data[soma->state.displayedPolycube];
VoxelSpace culledRepr = pinput->repr;
cullEmptySpace(&culledRepr);
uint32 newPolycubeHandle = createPolycubeFromRepr(soma->scene, &culledRepr, pinput->color);
SceneGraphNode *newPolycubeGraphNode = getSceneGraphNode(soma->scene, newPolycubeHandle);
newPolycubeGraphNode->rotation = getSceneGraphNode(soma->scene, currentPolycubeHandle)->rotation;
removeEntity(soma->scene, currentPolycubeHandle);
soma->polycubes.data[soma->state.displayedPolycube] = newPolycubeHandle;
sceneNodeAddNode(soma->scene, soma->scene->sceneRoot, newPolycubeHandle);
soma->state.polycubeDirty = false;
hide(soma->scene, currentPolycubeHandle);
show(soma->scene, newPolycubeHandle);
}
}
}
uint32 oldHandle = soma->polycubes.data[soma->state.displayedPolycube];
Quaternion rot = getSceneGraphNode(s, oldHandle)->rotation;
removeSceneGraphNode(s, oldHandle);
void createSolutionEntities(Arena *arena, Soma *soma) {
if (soma->solutions.length > 0) {
soma->solutionEntities = PushList(arena, HandleList, soma->solutions.length);
for (EachEl(soma->solutions, SomaSolution, solution)) {
uint32 solutionGraphNodeHandle = createSceneGraphNode(soma->scene);
AppendList(&soma->solutionEntities, solutionGraphNodeHandle);
sceneNodeAddNode(soma->renderer->scene, soma->renderer->scene->sceneRoot, solutionGraphNodeHandle);
for (EachIn(*solution, soln_i)) {
uint32 polycubeGraphNodeHandle = createPolycubeFromRepr(
soma->scene,
&(VoxelSpace){ solution->data[soln_i], 3, 3, 3 },
colorFromIndex(soln_i)
);
sceneNodeAddNode(soma->renderer->scene, solutionGraphNodeHandle, polycubeGraphNodeHandle);
}
PolycubeInput *newInput = &soma->polycubeInput.data[soma->state.displayedPolycube];
VoxelSpace newInputCulled = newInput->repr;
cullEmptySpace(&newInputCulled);
uint32 newHandle = createPolycubeFromRepr(s, &newInputCulled, newInput->color);
getSceneGraphNode(s, newHandle)->rotation = rot;
soma->polycubes.data[soma->state.displayedPolycube] = newHandle;
sceneNodeAddNode(s, s->sceneRoot, newHandle);
soma->state.polycubeDirty = false;
show(s, newHandle);
}
show(soma->scene, soma->solutionEntities.data[soma->state.displayedSolution]);
}
}
@@ -798,7 +796,8 @@ int mainGfx() {
Arena *arena = arenaAlloc(Megabytes(128));
Arena *solutionsArena = arenaAlloc(Megabytes(128));
int winWidth = 800, winHeight = 600;
int winWidth = 800;
int winHeight = 600;
GLFWwindow *windowHandle = initWindowAndGL(winWidth, winHeight);
if (!windowHandle) {
return 1;
@@ -840,9 +839,9 @@ int mainGfx() {
.taskStatus = SolveTaskStatus_Ready,
},
.state = {
.displayingSolutions = false,
.displayedPolycube = 0,
.displayedSolution = 0,
.displayingSolutions = false,
.displayedSolution = -1,
.isInitialState = true,
.light = createEntity(&mainScene),
.camera = mainFrame.cam,
@@ -871,10 +870,10 @@ int mainGfx() {
VoxelSpace voxelSpace = { stdSoma.data[i], 3, 3, 3 };
RLVector4 color = colorFromIndex(i);
PolycubeInput input = (PolycubeInput){ voxelSpace, color };
AppendList(&soma.polycubeInput, input);
ListAppend(soma.polycubeInput, input);
cullEmptySpace(&voxelSpace);
uint32 polycubeGraphNodeHandle = createPolycubeFromRepr(soma.scene, &voxelSpace, color);
AppendList(&soma.polycubes, polycubeGraphNodeHandle);
ListAppend(soma.polycubes, polycubeGraphNodeHandle);
sceneNodeAddNode(renderer.scene, renderer.scene->sceneRoot, polycubeGraphNodeHandle);
}
@@ -903,15 +902,13 @@ int mainGfx() {
processInput(&soma, &ui);
if (soma.solveTaskCtx.taskStatus == SolveTaskStatus_Complete) {
soma.solutions = PushFullList(solutionsArena, SomaSolutionList, soma.solveTaskCtx.solutions.length);
memcpy(soma.solutions.data, soma.solveTaskCtx.solutions.data, soma.solutions.length*sizeof(soma.solutions.data[0]));
for (EachIn(soma.solutions, i)) {
soma.solutions.data[i] = PushFullList(solutionsArena, SomaSolution, soma.solveTaskCtx.input.length);
memcpy(&soma.solutions.data[i], &soma.solveTaskCtx.solutions.data[i], soma.solveTaskCtx.input.length*sizeof(uint64));
soma.solutions = PushList(solutionsArena, SomaSolutionList, soma.solveTaskCtx.solutions.length);
for (EachIn(soma.solveTaskCtx.solutions, i)) {
ListAppend(soma.solutions, PushListCopy(solutionsArena, SomaSolution, soma.solveTaskCtx.solutions.data[i]));
}
createSolutionEntities(arena, &soma);
soma.solveTaskCtx.taskStatus = SolveTaskStatus_Ready;
soma.state.displayingSolutions = true;
soma.state.displayedSolution = 0;
arenaFreeFrom(soma.solveTaskCtx.arena, 0);
}

View File

@@ -289,15 +289,15 @@ void test() {
for (int i = 0; i < 6; i++) {
if (positions1.data[i] != expected_results1[i]) {
MismatchData data = { i, positions1.data[i], expected_results1[i] };
AppendList(&mismatches1, data);
ListAppend(mismatches1, data);
}
if (positions2.data[i] != expected_results2[i]) {
MismatchData data = { i, positions2.data[i], expected_results2[i] };
AppendList(&mismatches2, data);
ListAppend(mismatches2, data);
}
if (positions3.data[i] != expected_results3[i]) {
MismatchData data = { i, positions3.data[i], expected_results3[i] };
AppendList(&mismatches3, data);
ListAppend(mismatches3, data);
}
}
Assert(mismatches1.length == 0);

View File

@@ -1,44 +1,60 @@
#include "string.h"
#include "scene.h"
Entity *getEntity(Scene *s, uint32 entityHandle) {
if (entityHandle) {
return &s->entities.data[entityHandle - 1];
Entity *getEntity(Scene *s, int32 entityHandle) {
return &s->entities.data[entityHandle];
}
SceneGraphNode *getSceneGraphNode(Scene *s, int32 sceneGraphNodeHandle) {
return &s->graphNodes.data[sceneGraphNodeHandle];
}
SceneGraphNode *getSceneGraphNodeForEntity(Scene *s, int32 entityHandle) {
return getSceneGraphNode(s, getEntity(s, entityHandle)->graphNodeHandle);
}
int32 createSceneGraphNode(Scene *s) {
SceneGraphNode *newNode;
int32 newNodeHandle;
if (s->nextFreeNode) {
newNodeHandle = s->nextFreeNode;
newNode = getSceneGraphNode(s, newNodeHandle);
if (newNode->next) {
s->nextFreeNode = newNode->next;
} else {
s->nextFreeNode = 0;
}
newNode->next = 0;
} else {
ListAppend(s->graphNodes, (SceneGraphNode){0});
newNodeHandle = (int32)s->graphNodes.length - 1;
newNode = getSceneGraphNode(s, newNodeHandle);
newNode->nextSibling = 0;
}
return NULL;
initGraphNode(newNode);
return newNodeHandle;
}
SceneGraphNode *getSceneGraphNode(Scene *s, uint32 sceneGraphNodeHandle) {
if (sceneGraphNodeHandle) {
return &s->graphNodes.data[sceneGraphNodeHandle - 1];
int32 createEntity(Scene *s) {
Entity *newEntity;
int32 newEntityHandle;
println("%d", s->nextFreeEntity);
if (s->nextFreeEntity) {
newEntityHandle = s->nextFreeEntity;
newEntity = getEntity(s, newEntityHandle);
if (newEntity->next) {
s->nextFreeEntity = newEntity->next;
} else {
s->nextFreeEntity = 0;
}
newEntity->next = 0;
} else {
ListAppend(s->entities, (Entity){0});
newEntityHandle = (int32)s->entities.length - 1;
newEntity = getEntity(s, newEntityHandle);
}
return NULL;
}
SceneGraphNode *getSceneGraphNodeForEntity(Scene *s, uint32 entityHandle) {
Entity *e = getEntity(s, entityHandle);
if (e) {
return getSceneGraphNode(s, e->graphNodeHandle);
}
return NULL;
}
uint32 createSceneGraphNode(Scene *s) {
AppendList(&s->graphNodes, (SceneGraphNode){0});
SceneGraphNode *node = &s->graphNodes.data[s->graphNodes.length - 1];
node->children = PushList(s->arena, HandleList, 1000);
initGraphNode(node);
return (uint32)s->graphNodes.length;
}
uint32 createEntity(Scene *s) {
AppendList(&s->entities, (Entity){0});
uint32 graphNodeId = createSceneGraphNode(s);
s->entities.data[s->entities.length - 1].graphNodeHandle = graphNodeId;
getSceneGraphNode(s, graphNodeId)->entityHandle = (uint32)s->entities.length;
uint32 handle = (uint32)s->entities.length;
uint32 graphNodeHandle = (uint32)s->graphNodes.length;
return handle;
newEntity->graphNodeHandle = createSceneGraphNode(s);
getSceneGraphNodeForEntity(s, newEntityHandle)->entityHandle = newEntityHandle;
return newEntityHandle;
}
void initGraphNode(SceneGraphNode *n) {
@@ -49,32 +65,32 @@ void initGraphNode(SceneGraphNode *n) {
n->world = n->local;
}
void recalcGraphNode(SceneGraphNode *n) {
n->local = MatrixCompose(n->translation, n->rotation, n->scale);
}
Scene createScene(Arena *arena) {
Scene result = {
.arena = arena,
.entities = PushList(arena, EntityList, 100000),
.graphNodes = PushList(arena, SceneGraphNodeList, 100000),
.entities = PushListZero(arena, EntityList, 100000),
.nextFreeEntity = 0,
.graphNodes = PushListZero(arena, SceneGraphNodeList, 100000),
.nextFreeNode = 0,
};
int32 handle = createEntity(&result); // Intialise the "zero" nodes
getEntity(&result, handle)->flags = EntityFlags_None | EntityFlags_Dead;
result.sceneRoot = createSceneGraphNode(&result);
return result;
}
void recalcSceneGraphNode(Scene *s, uint32 parentHandle) {
SceneGraphNode *node = getSceneGraphNode(s, parentHandle);
if (node->entityHandle) {
getEntity(s, node->entityHandle)->flags |= EntityFlags_Render;
}
for (EachIn(node->children, i)) {
uint32 nodeId = node->children.data[i];
SceneGraphNode *graphNode = getSceneGraphNode(s, nodeId);
graphNode->parentHandle = parentHandle;
recalcGraphNode(graphNode);
graphNode->world = MatrixMultiply(graphNode->local, node->world);
recalcSceneGraphNode(s, nodeId);
void recalcSceneGraphNode(Scene *s, int32 parentHandle) {
if (!parentHandle) return;
SceneGraphNode *parentNode = getSceneGraphNode(s, parentHandle);
getEntity(s, parentNode->entityHandle)->flags |= EntityFlags_Render;
int32 nextChild = parentNode->firstChild;
while (nextChild) {
SceneGraphNode *childNode = getSceneGraphNode(s, nextChild);
childNode->parentHandle = parentHandle;
childNode->local = MatrixCompose(childNode->translation, childNode->rotation, childNode->scale);
childNode->world = MatrixMultiply(childNode->local, parentNode->world);
recalcSceneGraphNode(s, nextChild);
nextChild = childNode->nextSibling;
}
}
@@ -82,31 +98,73 @@ void recalcScene(Scene *s) {
recalcSceneGraphNode(s, s->sceneRoot);
}
void removeEntity(Scene *s, uint32 entityHandle) {
Entity *entity = getEntity(s, entityHandle);
entity->flags |= EntityFlags_Dead;
SceneGraphNode *graphNode = getSceneGraphNode(s, entity->graphNodeHandle);
if (graphNode != NULL && graphNode->parentHandle) {
function void removeSceneGraphNodeRecursive(Scene *s, int32 graphNodeHandle, bool deletingParent) {
if (!graphNodeHandle) return;
SceneGraphNode *graphNode = getSceneGraphNode(s, graphNodeHandle);
int32 nextChild = graphNode->firstChild;
while (nextChild) {
int32 sibling = getSceneGraphNode(s, nextChild)->nextSibling;
removeSceneGraphNodeRecursive(s, nextChild, true);
nextChild = sibling;
}
if (graphNode->entityHandle) {
Entity *entity = getEntity(s, graphNode->entityHandle);
*entity = (Entity){0};
if (s->nextFreeEntity) {
entity->next = s->nextFreeEntity;
}
s->nextFreeEntity = graphNode->entityHandle;
}
if (s->nextFreeNode) {
graphNode->next = s->nextFreeNode;
}
s->nextFreeNode = graphNodeHandle;
if (!deletingParent && graphNode->parentHandle) {
SceneGraphNode *parentNode = getSceneGraphNode(s, graphNode->parentHandle);
if (parentNode != NULL) {
for (EachIn(parentNode->children, i)) {
if (parentNode->children.data[i] == entity->graphNodeHandle) {
memcpy(parentNode->children.data + i, parentNode->children.data + i + 1, parentNode->children.length - i - 1);
//ListRemove(&parentNode->children, i);
graphNode->parentHandle = 0;
if (parentNode->firstChild == graphNodeHandle) {
if (graphNode->nextSibling) {
parentNode->firstChild = graphNode->nextSibling;
} else {
parentNode->firstChild = 0;
}
} else {
int32 prevSibling = parentNode->firstChild;
int32 nextSibling = getSceneGraphNode(s, parentNode->firstChild)->nextSibling;
while (nextSibling) {
SceneGraphNode *siblingNode = getSceneGraphNode(s, nextSibling);
if (nextSibling == graphNodeHandle) {
SceneGraphNode *prevSiblingNode = getSceneGraphNode(s, prevSibling);
prevSiblingNode->nextSibling = graphNode->nextSibling;
break;
}
nextSibling = siblingNode->nextSibling;
}
}
}
graphNode->firstChild = 0;
graphNode->parentHandle = 0;
graphNode->entityHandle = 0;
graphNode->nextSibling = 0;
}
void sceneNodeAddEntity(Scene *s, uint32 graphNodeHandle, uint32 entityHandle) {
HandleList *childList = &getSceneGraphNode(s, graphNodeHandle)->children;
AppendList(childList, getEntity(s, entityHandle)->graphNodeHandle);
void removeSceneGraphNode(Scene *s, int32 graphNodeHandle) {
removeSceneGraphNodeRecursive(s, graphNodeHandle, false);
}
void sceneNodeAddNode(Scene *s, uint32 recipientNodeHandle, uint32 graphNodeHandle) {
HandleList *childList = &getSceneGraphNode(s, recipientNodeHandle)->children;
AppendList(childList, graphNodeHandle);
void removeEntity(Scene *s, int32 entityHandle) {
if (!entityHandle) return;
removeSceneGraphNode(s, getEntity(s, entityHandle)->graphNodeHandle);
}
void sceneNodeAddNode(Scene *s, int32 parentHandle, int32 childHandle) {
SceneGraphNode *parentNode = getSceneGraphNode(s, parentHandle);
SceneGraphNode *childNode = getSceneGraphNode(s, childHandle);
childNode->nextSibling = parentNode->firstChild;
parentNode->firstChild = childHandle;
childNode->parentHandle = parentHandle;
}

View File

@@ -1,9 +1,10 @@
#include "../gfx/gfx.h"
#include "../lib/raymath.h"
DefineList(uint32, Handle);
DefineList(int32, Handle);
enum EntityFlags {
EntityFlags_None=0,
EntityFlags_Visible=1<<0,
EntityFlags_Dead=1<<1,
EntityFlags_Render=1<<2,
@@ -11,11 +12,14 @@ enum EntityFlags {
typedef struct Entity Entity;
struct Entity {
uint32 graphNodeHandle;
int32 graphNodeHandle;
uint64 flags;
RLVector4 color;
Mesh *mesh;
Texture *tex;
// Free list
int32 next;
};
DefineList(Entity, Entity);
@@ -26,30 +30,36 @@ struct SceneGraphNode {
RLVector3 translation;
Quaternion rotation;
RLVector3 scale;
HandleList children;
uint32 entityHandle;
uint32 parentHandle;
int32 entityHandle;
int32 parentHandle;
// Free list
int32 next;
// Children
int32 nextSibling;
int32 firstChild;
};
DefineList(SceneGraphNode, SceneGraphNode);
typedef struct Scene Scene;
struct Scene {
uint32 sceneRoot;
int32 sceneRoot;
EntityList entities;
int32 nextFreeEntity;
SceneGraphNodeList graphNodes;
Arena *arena;
int32 nextFreeNode;
};
uint32 createEntity(Scene *s);
Entity *getEntity(Scene *s, uint32 id);
SceneGraphNode *getSceneGraphNode(Scene *s, uint32 id);
uint32 createSceneGraphNode(Scene *s);
int32 createEntity(Scene *s);
Entity *getEntity(Scene *s, int32 id);
SceneGraphNode *getSceneGraphNode(Scene *s, int32 id);
int32 createSceneGraphNode(Scene *s);
Scene createScene(Arena *arena);
void initGraphNode(SceneGraphNode *n);
void recalcGraphNode(SceneGraphNode *n);
void recalcSceneGraphNode(Scene *s, uint32 parentHandle);
void recalcSceneGraphNode(Scene *s, int32 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);
void removeEntity(Scene *s, int32 entityHandle);
void removeSceneGraphNode(Scene *s, int32 graphNodeHandle);
void sceneNodeAddNode(Scene *s, int32 recipientNodeHandle, int32 graphNodeHandle);
SceneGraphNode *getSceneGraphNodeForEntity(Scene *s, int32 entityHandle);