ECS rendering

This commit is contained in:
2025-08-22 16:15:42 -05:00
parent 94ad64675d
commit f9385ed233
17 changed files with 161 additions and 215 deletions

View File

@@ -17,111 +17,37 @@ ecscomponent_t NODE_COMPONENT = ecsComponentInit(
})
);
ecsid_t nodeParentGet(const ecsid_t child) {
assertTrue(child >= 0 && child < ECS_ENTITY_COUNT_MAX, "Invalid child ID");
if(!nodeHas(child)) return -1;
return NODE_DATA[child].parent;
}
uint8_t nodeChildGetAll(const ecsid_t id, ecsid_t *children) {
if(!nodeHas(id)) return 0;
if(children == NULL) return NODE_DATA[id].childCount;
memoryCopy(
children,
NODE_DATA[id].children,
sizeof(ecsid_t) * NODE_DATA[id].childCount
);
return NODE_DATA[id].childCount;
}
void nodeChildAdd(const ecsid_t parent, const ecsid_t child) {
if(!nodeHas(parent)) nodeAdd(parent);
if(!nodeHas(child)) nodeAdd(child);
node_t *parentNode = &NODE_DATA[parent];
assertTrue(parentNode->childCount < SCENE_ITEM_CHILD_MAX, "Parent full.");
// Add child to parent's children array
parentNode->children[parentNode->childCount] = child;
parentNode->childCount++;
// Set child's parent
NODE_DATA[child].parent = parent;
}
void nodeChildRemove(const ecsid_t parent, const ecsid_t child) {
assertTrue(nodeHas(parent), "NODE ECS lacks Parent.");
assertTrue(nodeHas(child), "NODE ECS lacks Child.");
node_t *childNode = &NODE_DATA[child];
node_t *parentNode = &NODE_DATA[parent];
assertTrue(childNode->parent == parent, "Child does not belong to parent");
assertTrue(parentNode->childCount > 0, "Parent has no children");
// Remove child from parent's children array
for (uint8_t i = 0; i < parentNode->childCount; i++) {
if (parentNode->children[i] == child) {
// Shift remaining children down
for (uint8_t j = i; j < parentNode->childCount - 1; j++) {
parentNode->children[j] = parentNode->children[j + 1];
}
parentNode->childCount--;
break;
}
}
// Clear child's parent
childNode->parent = -1;
if(childNode->childCount == 0) nodeRemove(child);
if(parentNode->childCount == 0) nodeRemove(parent);
}
void nodeChildRemoveAll(const ecsid_t parent) {
assertTrue(nodeHas(parent), "NODE ECS lacks Parent.");
node_t *parentNode = &NODE_DATA[parent];
for(uint8_t i = 0; i < parentNode->childCount; i++) {
ecsid_t child = parentNode->children[i];
NODE_DATA[child].parent = -1;
if(NODE_DATA[child].childCount == 0) nodeRemove(child);
}
nodeRemove(parent);
}
bool_t nodeChildInTree(const ecsid_t parent, const ecsid_t child) {
assertTrue(nodeHas(parent), "NODE ECS lacks Parent.");
assertTrue(nodeHas(child), "NODE ECS lacks Child.");
assertTrue(parent >= 0 && parent < ECS_ENTITY_COUNT_MAX, "Invalid parent ID");
assertTrue(child >= 0 && child < ECS_ENTITY_COUNT_MAX, "Invalid child ID");
assertTrue(parent != child, "Child cannot be a child of itself.");
node_t *childNode = &NODE_DATA[child];
while(childNode) {
if(childNode->parent == parent) return true;
if(childNode->parent == -1) break; // No parent means we've reached the root
childNode = &NODE_DATA[childNode->parent];
}
return false;
}
void nodeInit(void) {
for(ecsid_t i = 0; i < ECS_ENTITY_COUNT_MAX; i++) {
NODE_DATA[i].parent = -1;
}
}
void nodeEntityAdded(const ecsid_t id) {
NODE_DATA[id].parent = -1;
glm_mat4_identity(NODE_DATA[id].transform);
}
void nodeEntityRemoved(const ecsid_t id) {
if(NODE_DATA[id].parent == -1) return;
nodeChildRemove(NODE_DATA[id].parent, id);
}
void nodeMatrixGet(const ecsid_t id, mat4 dest) {
node_t *node;
if(nodeHas(id)) {
node = &NODE_DATA[id];
} else {
node = nodeAdd(id);
}
glm_mat4_copy(node->transform, dest);
}
void nodeMatrixSet(const ecsid_t id, mat4 in) {
node_t *node;
if(nodeHas(id)) {
node = &NODE_DATA[id];
} else {
node = nodeAdd(id);
}
glm_mat4_copy(in, node->transform);
}

View File

@@ -11,13 +11,7 @@
#define SCENE_ITEM_CHILD_MAX 16
typedef struct {
ecsid_t children[SCENE_ITEM_CHILD_MAX];
uint8_t childCount;
ecsid_t parent;
vec3 position;
vec3 rotation;
vec3 scale;
mat4 transform;
} node_t;
extern node_t NODE_DATA[ECS_ENTITY_COUNT_MAX];
@@ -30,64 +24,6 @@ extern ecscomponent_t NODE_COMPONENT;
((node_t*)ecsComponentDataAdd(&NODE_COMPONENT, id))
#define nodeRemove(id) ecsComponentDataRemove(&NODE_COMPONENT, id)
/**
* Create a new scene item in the scene tree.
* This will create a new entity in the ECS and return its ID.
*
* @return The ID of the newly created scene item.
*/
ecsid_t nodeCreate(void);
/**
* Get the parent of a given scene item.
*
* @param id The ID of the scene item.
* @return The ID of the parent scene item, or -1 if it has no parent.
*/
ecsid_t nodeParentGet(const ecsid_t child);
/**
* Get the children of a given scene item. If children is NULL only the count
* will be returned.
*
* @param id The ID of the scene item.
* @param children Pointer to an array where the children IDs will be stored.
* @return The number of children found.
*/
uint8_t nodeChildGetAll(const ecsid_t id, ecsid_t *children);
/**
* Add a child to a parent in the scene tree.
*
* @param parent The ID of the parent scene item.
* @param child The ID of the child scene item to add.
*/
void nodeChildAdd(const ecsid_t parent, const ecsid_t child);
/**
* Remove a child from a parent in the scene tree.
*
* @param prnt The ID of the parent scene item.
* @param child The ID of the child scene item to remove.
*/
void nodeChildRemove(const ecsid_t prnt, const ecsid_t child);
/**
* Remove all children from a parent in the scene tree.
*
* @param parent The ID of the parent scene item.
*/
void nodeChildRemoveAll(const ecsid_t parent);
/**
* Returns true if the child is within the parent's children, recursively.
*
* @param parent The ID of the parent scene item.
* @param child The ID of the child scene item to check.
* @return True if the child is in the parent's children, false otherwise.
*/
bool_t nodeChildInTree(const ecsid_t parent, const ecsid_t child);
/**
* Initialize the scene tree.
*
@@ -109,4 +45,20 @@ void nodeEntityAdded(const ecsid_t id);
*
* @param id The ID of the entity being removed.
*/
void nodeEntityRemoved(const ecsid_t id);
void nodeEntityRemoved(const ecsid_t id);
/**
* Get the local transformation matrix of a scene item.
*
* @param id The ID of the scene item.
* @param out Pointer to a mat4 where the local matrix will be stored.
*/
void nodeMatrixGet(const ecsid_t id, mat4 out);
/**
* Set the local transformation matrix of a scene item.
*
* @param id The ID of the scene item.
* @param in Pointer to a mat4 containing the new local matrix.
*/
void nodeMatrixSet(const ecsid_t id, mat4 in);

View File

@@ -9,23 +9,35 @@
#include "scene/node.h"
#include "display/camera.h"
#include "display/display.h"
#include "display/mesh/meshrenderer.h"
ecsid_t sceneTestAdd(void) {
ecsid_t id = ecsEntityAdd();
mesh_t mesh;
meshvertex_t triangle[3] = {
{{255, 0, 0, 255}, {0.0f, 0.0f}, {1.0f, 0.0f}}, // Vertex 1
{{0, 255, 0, 255}, {1.0f, 0.0f}, {-1.0f, 0.0f}}, // Vertex 2
{{0, 0, 255, 255}, {0.5f, 1.0f}, {0, 2.0f}} // Vertex 3
};
void sceneTestAdd(void) {
meshInit(&mesh, MESH_PRIMITIVE_TRIANGLES, 3, triangle);
// Initialize the entity with a camera component
ecsid_t camera = ecsEntityAdd();
nodeChildAdd(id, camera);
node_t *node = nodeAdd(camera);
camera_t *camData = cameraAdd(camera);
camData->type = CAMERA_TYPE_ORTHOGRAPHIC;
camData->orthographic.left = 0.0f;
camData->orthographic.right = 1.0f;
camData->orthographic.top = 0.0f;
camData->orthographic.bottom = 1.0f;
camData->nearClip = -1.0f;
camData->farClip = 1.0f;
mat4 lookAt;
glm_lookat(
(vec3){ 3.0f, 3.0f, 3.0f },
(vec3){ 0.0f, 0.0f, 0.0f },
(vec3){ 0.0f, 1.0f, 0.0f },
lookAt
);
nodeMatrixSet(camera, lookAt);
// Optionally, you can set other properties or components here
return id;
// Test cube
ecsid_t cube = ecsEntityAdd();
node = nodeAdd(cube);
meshrenderer_t *renderer = meshRendererAdd(cube);
renderer->mesh = &mesh;
}

View File

@@ -8,4 +8,4 @@
#pragma once
#include "ecs/ecssystem.h"
ecsid_t sceneTestAdd(void);
void sceneTestAdd(void);