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

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