ECS rendering
This commit is contained in:
@@ -8,6 +8,7 @@ target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
display.c
|
||||
camera.c
|
||||
renderer.c
|
||||
)
|
||||
|
||||
# Subdirectories
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include "camera.h"
|
||||
#include "display/display.h"
|
||||
#include "assert/assert.h"
|
||||
#include "scene/node.h"
|
||||
|
||||
camera_t CAMERA_DATA[ECS_ENTITY_COUNT_MAX] = { 0 };
|
||||
ecscomponent_t CAMERA_COMPONENT = ecsComponentInit(
|
||||
@@ -24,8 +25,8 @@ void cameraEntityAdded(const ecsid_t id) {
|
||||
if(CAMERA_MAIN == -1) CAMERA_MAIN = id;
|
||||
|
||||
camera_t *cam = cameraGet(id);
|
||||
cam->type = CAMERA_TYPE_ORTHOGRAPHIC;
|
||||
cam->perspective.fov = glm_rad(75.0f);
|
||||
cam->type = CAMERA_TYPE_PERSPECTIVE;
|
||||
cam->perspective.fov = glm_rad(90.0f);
|
||||
cam->nearClip = 0.1f;
|
||||
cam->farClip = 1000.0f;
|
||||
cam->clearColor = COLOR_CORNFLOWER_BLUE;
|
||||
@@ -36,7 +37,9 @@ void cameraPush(const ecsid_t id) {
|
||||
|
||||
camera_t *cam = cameraGet(id);
|
||||
|
||||
mat4 projection;
|
||||
mat4 projection, view;
|
||||
nodeMatrixGet(id, view);
|
||||
|
||||
switch(cam->type) {
|
||||
case CAMERA_TYPE_ORTHOGRAPHIC:
|
||||
glm_ortho(
|
||||
@@ -61,10 +64,13 @@ void cameraPush(const ecsid_t id) {
|
||||
}
|
||||
|
||||
#if DUSK_DISPLAY_SDL2
|
||||
mat4 pv;
|
||||
glm_mat4_mul(projection, view, pv);
|
||||
|
||||
glPushMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glLoadMatrixf((const GLfloat*)projection);
|
||||
glLoadMatrixf((const GLfloat*)pv);
|
||||
|
||||
glClearColor(
|
||||
cam->clearColor.r / 255.0f,
|
||||
@@ -73,6 +79,9 @@ void cameraPush(const ecsid_t id) {
|
||||
cam->clearColor.a / 255.0f
|
||||
);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -7,18 +7,11 @@
|
||||
|
||||
#include "display/display.h"
|
||||
#include "console/console.h"
|
||||
#include "display/camera.h"
|
||||
#include "display/mesh/mesh.h"
|
||||
#include "display/renderer.h"
|
||||
#include "ecs/ecssystem.h"
|
||||
|
||||
display_t DISPLAY;
|
||||
|
||||
mesh_t mesh;
|
||||
meshvertex_t triangle[3] = {
|
||||
{{255, 0, 0, 255}, {0.0f, 0.0f}, {0.0f, 1.0f}}, // Vertex 1
|
||||
{{0, 255, 0, 255}, {1.0f, 0.0f}, {1.0f, 1.0f}}, // Vertex 2
|
||||
{{0, 0, 255, 255}, {0.5f, 1.0f}, {0.5f, 0.0f}} // Vertex 3
|
||||
};
|
||||
|
||||
errorret_t displayInit(void) {
|
||||
#if DUSK_DISPLAY_SDL2
|
||||
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) != 0) {
|
||||
@@ -61,8 +54,6 @@ errorret_t displayInit(void) {
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
#endif
|
||||
|
||||
meshInit(&mesh, MESH_PRIMITIVE_TRIANGLES, 3, triangle);
|
||||
|
||||
// For now, we just return an OK error.
|
||||
errorOk();
|
||||
@@ -88,11 +79,7 @@ errorret_t displayUpdate(void) {
|
||||
glViewport(0, 0, windowWidth, windowHeight);
|
||||
#endif
|
||||
|
||||
if(CAMERA_MAIN != -1) {
|
||||
cameraPush(CAMERA_MAIN);
|
||||
meshDraw(&mesh, 0, -1);
|
||||
cameraPop();
|
||||
}
|
||||
rendererRender(CAMERA_MAIN);
|
||||
|
||||
#if DUSK_DISPLAY_SDL2
|
||||
SDL_GL_SwapWindow(DISPLAY.window);
|
||||
@@ -103,8 +90,6 @@ errorret_t displayUpdate(void) {
|
||||
}
|
||||
|
||||
errorret_t displayDispose(void) {
|
||||
meshDispose(&mesh);
|
||||
|
||||
#if DUSK_DISPLAY_SDL2
|
||||
if(DISPLAY.glContext) {
|
||||
SDL_GL_DeleteContext(DISPLAY.glContext);
|
||||
|
@@ -8,4 +8,5 @@ target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
mesh.c
|
||||
quad.c
|
||||
meshrenderer.c
|
||||
)
|
@@ -18,10 +18,9 @@ ecscomponent_t MESH_RENDERER_COMPONENT = ecsComponentInit(
|
||||
);
|
||||
|
||||
void meshRendererDraw(const ecsid_t id) {
|
||||
if (!meshRendererHas(id)) return;
|
||||
|
||||
meshrenderer_t *renderer = meshRendererGet(id);
|
||||
if (!renderer || !renderer->mesh) return;
|
||||
if(!meshRendererHas(id)) return;
|
||||
|
||||
meshrenderer_t *renderer = &MESH_RENDERER_DATA[id];
|
||||
if(!renderer->mesh) return;
|
||||
meshDraw(renderer->mesh, 0, -1);
|
||||
}
|
@@ -24,6 +24,8 @@ extern ecscomponent_t MESH_RENDERER_COMPONENT;
|
||||
(ecsComponentDataHas(&MESH_RENDERER_COMPONENT, id))
|
||||
#define meshRendererRemove(id) \
|
||||
ecsComponentDataRemove(&MESH_RENDERER_COMPONENT, id)
|
||||
#define meshRendererGetAll(out) \
|
||||
ecsComponentGetAll(&MESH_RENDERER_COMPONENT, out)
|
||||
|
||||
/**
|
||||
* Draw the mesh for the given entity.
|
24
src/display/renderer.c
Normal file
24
src/display/renderer.c
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "renderer.h"
|
||||
#include "display/mesh/meshrenderer.h"
|
||||
|
||||
void rendererRender(const ecsid_t camera) {
|
||||
if(camera == -1) return;
|
||||
|
||||
// Get the meshes.
|
||||
uint32_t meshCount;
|
||||
ecsid_t meshes[ECS_ENTITY_COUNT_MAX];
|
||||
meshCount = meshRendererGetAll(meshes);
|
||||
|
||||
cameraPush(camera);
|
||||
for(uint32_t i = 0; i < meshCount; i++) {
|
||||
meshRendererDraw(meshes[i]);
|
||||
}
|
||||
cameraPop();
|
||||
}
|
16
src/display/renderer.h
Normal file
16
src/display/renderer.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "display/camera.h"
|
||||
|
||||
/**
|
||||
* Render the given scene from the perspective of the given camera.
|
||||
*
|
||||
* @param camera The ID of the camera entity to render from.
|
||||
*/
|
||||
void rendererRender(const ecsid_t camera);
|
@@ -58,8 +58,7 @@ void * ecsComponentDataAdd(ecscomponent_t *cmp, const ecsid_t id) {
|
||||
);
|
||||
cmp->entityFlags[id] |= ECS_COMPONENT_ENTITY_FLAG_USED;
|
||||
if(cmp->callbacks.entityAdd) cmp->callbacks.entityAdd(id);
|
||||
cmp->entitiesWithData[id] = id;
|
||||
cmp->entitiesWithDataCount++;
|
||||
cmp->entitiesWithData[cmp->entitiesWithDataCount++] = id;
|
||||
|
||||
return ecsComponentDataGet(cmp, id);
|
||||
}
|
||||
@@ -92,6 +91,22 @@ void ecsComponentDataRemove(ecscomponent_t *cmp, const ecsid_t id) {
|
||||
if(cmp->callbacks.entityRemove) cmp->callbacks.entityRemove(id);
|
||||
}
|
||||
|
||||
uint32_t ecsComponentGetAll(const ecscomponent_t *cmp, ecsid_t *out) {
|
||||
assertTrue(
|
||||
ecsComponentIsInitialized(cmp),
|
||||
"Component was never initialized."
|
||||
);
|
||||
|
||||
if(!out) return cmp->entitiesWithDataCount;
|
||||
|
||||
memoryCopy(
|
||||
out,
|
||||
cmp->entitiesWithData,
|
||||
sizeof(ecsid_t) * cmp->entitiesWithDataCount
|
||||
);
|
||||
return cmp->entitiesWithDataCount;
|
||||
}
|
||||
|
||||
void ecsComponentDispose(ecscomponent_t *cmp) {
|
||||
assertNotNull(cmp, "Component pointer cannot be NULL.");
|
||||
assertTrue(
|
||||
|
@@ -93,6 +93,16 @@ void * ecsComponentDataAdd(ecscomponent_t *cmp, const ecsid_t id);
|
||||
*/
|
||||
void ecsComponentDataRemove(ecscomponent_t *cmp, const ecsid_t id);
|
||||
|
||||
/**
|
||||
* Gets all entities that have data in the component. Passing NULL for out will
|
||||
* just return the count of entities.
|
||||
*
|
||||
* @param cmp Pointer to the ecscomponent_t.
|
||||
* @param out Pointer to an array to store the entity IDs.
|
||||
* @return The number of entities with data.
|
||||
*/
|
||||
uint32_t ecsComponentGetAll(const ecscomponent_t *cmp, ecsid_t *out);
|
||||
|
||||
/**
|
||||
* Disposes the component, freeing any resources it holds.
|
||||
*
|
||||
|
@@ -24,9 +24,6 @@ void ecsSystemInit() {
|
||||
ECS_SYSTEM.available[i] = &ECS_SYSTEM.entities[i];
|
||||
}
|
||||
ECS_SYSTEM.availableCount = ECS_ENTITY_COUNT_MAX;
|
||||
|
||||
// Reserve root entity
|
||||
ECS_SYSTEM.root = ecsEntityAdd();
|
||||
}
|
||||
|
||||
ecsid_t ecsEntityAdd() {
|
||||
|
@@ -19,8 +19,6 @@ typedef struct {
|
||||
|
||||
ecscomponent_t *components[ECS_SYSTEM_ECS_COMPONENTS_MAX];
|
||||
uint32_t componentCount;
|
||||
|
||||
ecsid_t root;
|
||||
} ecssystem_t;
|
||||
|
||||
extern ecssystem_t ECS_SYSTEM;
|
||||
|
@@ -27,8 +27,7 @@ errorret_t engineInit(void) {
|
||||
ecsSystemInit();
|
||||
errorChain(displayInit());
|
||||
|
||||
ecsid_t sceneTest = sceneTestAdd();
|
||||
nodeChildAdd(ECS_SYSTEM.root, sceneTest);
|
||||
sceneTestAdd();
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
126
src/scene/node.c
126
src/scene/node.c
@@ -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);
|
||||
}
|
@@ -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);
|
@@ -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;
|
||||
}
|
@@ -8,4 +8,4 @@
|
||||
#pragma once
|
||||
#include "ecs/ecssystem.h"
|
||||
|
||||
ecsid_t sceneTestAdd(void);
|
||||
void sceneTestAdd(void);
|
Reference in New Issue
Block a user