diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-05-09 20:40:56 -0400 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-05-09 20:40:56 -0400 |
| commit | ecf91229fb5c9150f2d60d97652bf0024a5c3435 (patch) | |
| tree | d8fcffa8d436222c4304d9f4d538165ddd734055 | |
| parent | 9693ff2d4be85d356e07e3192baaa2262a7140ff (diff) | |
pke-test-serialization: add more complex tests
| -rw-r--r-- | src/camera.cpp | 2 | ||||
| -rw-r--r-- | src/components.hpp | 1 | ||||
| -rw-r--r-- | src/ecs.cpp | 22 | ||||
| -rw-r--r-- | src/ecs.hpp | 2 | ||||
| -rw-r--r-- | src/entities.cpp | 5 | ||||
| -rw-r--r-- | src/serialization-camera.cpp | 78 | ||||
| -rw-r--r-- | src/serialization-component.cpp | 147 | ||||
| -rw-r--r-- | src/serialization.cpp | 49 | ||||
| -rw-r--r-- | src/serialization.hpp | 18 | ||||
| -rw-r--r-- | tests/pke-test-serialization.cpp | 274 |
10 files changed, 453 insertions, 145 deletions
diff --git a/src/camera.cpp b/src/camera.cpp index 8b7abe9..e734994 100644 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -55,7 +55,7 @@ PkeCamera &PkeCamera_Register(pk_uuid uuid, const InstPos &instPos) { cam.uuid = uuid; ECS_CreateEntity(&cam, nullptr); cam.camHandle = cameraHandle; - inst = ECS_CreateInstance(&cam, pk_uuid_zed, nullptr); + inst = ECS_CreateInstance(&cam, pk_uuid_zed, nullptr, nullptr); return PkeCamera_Register_Inner(cam, *inst, instPos); } diff --git a/src/components.hpp b/src/components.hpp index 968cd23..eebe43b 100644 --- a/src/components.hpp +++ b/src/components.hpp @@ -71,6 +71,7 @@ struct InstPos { btScalar mass; }; struct InstBt { + btCollisionShape *collision_shape = nullptr; btDefaultMotionState *motionState = nullptr; btRigidBody *rigidBody = nullptr; }; diff --git a/src/ecs.cpp b/src/ecs.cpp index 4f81ac0..9de7866 100644 --- a/src/ecs.cpp +++ b/src/ecs.cpp @@ -439,7 +439,7 @@ CompGrBinds *ECS_GetGrBinds(pk_handle_bucket_index_T bucketIndex, pk_handle_item return ecs.bc.grBinds.buckets[bucketIndex]; } -CompInstance *ECS_CreateInstance(Entity_Base *entity, pk_uuid uuid, CompGrBinds *entityTypeGrBinds) { +CompInstance *ECS_CreateInstance(Entity_Base *entity, pk_uuid uuid, CompGrBinds *entityTypeGrBinds, InstPos *inst_pos) { assert(entity != nullptr && entity != CAFE_BABE(Entity_Base)); InstanceHandle instanceHandle{Buckets_NewHandle(ecs.bc.instances)}; @@ -461,6 +461,26 @@ CompInstance *ECS_CreateInstance(Entity_Base *entity, pk_uuid uuid, CompGrBinds if (entityTypeGrBinds->instanceCounter > entityTypeGrBinds->instanceBufferMaxCount) { EntitiesWithExcessInstances.Push(ECS_GetEntity(entityTypeGrBinds->entHandle)); } + } else if (inst_pos != nullptr) { + // TODO leaky + comp->bt.collision_shape = pk_new<btSphereShape>(MemBkt_Bullet); + new (comp->bt.collision_shape) btSphereShape(1.0); + + btVector3 localInertia(0, 0, 0); + comp->bt.collision_shape->calculateLocalInertia(inst_pos->mass, localInertia); + comp->bt.motionState = pk_new<btDefaultMotionState>(MemBkt_Bullet); + new (comp->bt.motionState) btDefaultMotionState(inst_pos->posRot); + + comp->bt.rigidBody = pk_new<btRigidBody>(MemBkt_Bullet); + new (comp->bt.rigidBody) btRigidBody(inst_pos->mass, comp->bt.motionState, comp->bt.collision_shape, localInertia); + + comp->bt.rigidBody->setLinearVelocity(btVector3(0,0,0)); + comp->bt.rigidBody->setAngularVelocity(btVector3(0,0,0)); + comp->bt.rigidBody->getCollisionShape()->setLocalScaling(inst_pos->scale); + BtDynamicsWorld->addRigidBody(comp->bt.rigidBody); + comp->bt.rigidBody->getBroadphaseProxy()->m_collisionFilterGroup = static_cast<PhysicsCollision_T>(comp->physicsLayer); + comp->bt.rigidBody->getBroadphaseProxy()->m_collisionFilterMask = static_cast<PhysicsCollision_T>(comp->physicsMask); + comp->bt.rigidBody->setUserPointer(reinterpret_cast<void *>(comp)); } return comp; diff --git a/src/ecs.hpp b/src/ecs.hpp index e086ab6..b25fdb7 100644 --- a/src/ecs.hpp +++ b/src/ecs.hpp @@ -27,7 +27,7 @@ void ECS_GetGrBinds(Entity_Base *entity, pk_arr_t<CompGrBinds *> &arr); uint64_t ECS_GetGrBinds_BucketCount(); CompGrBinds *ECS_GetGrBinds(pk_handle_bucket_index_T bucketIndex, pk_handle_item_index_T &itemCount); -CompInstance *ECS_CreateInstance(Entity_Base *entity, pk_uuid uuid, CompGrBinds *entityTypeGrBinds); +CompInstance *ECS_CreateInstance(Entity_Base *entity, pk_uuid uuid, CompGrBinds *entityTypeGrBinds, InstPos *instance_pos); CompInstance *ECS_GetInstance(InstanceHandle instanceHandle); void ECS_GetInstances(Entity_Base *entity, pk_arr_t<CompInstance *> &arr); void ECS_UpdateInstance(CompInstance *instance, const InstPos &instPos, bool overridePhysics = false); diff --git a/src/entities.cpp b/src/entities.cpp index 0ab040c..860907c 100644 --- a/src/entities.cpp +++ b/src/entities.cpp @@ -52,7 +52,7 @@ Entity_Base *EntityType_CreateGenericInstance(EntityType *et, Entity_Base *level for (int64_t i = 0; i < et->detailsCount; ++i) { auto &etd = et->details[i]; - auto *compInst = ECS_CreateInstance(genericEntity, uuid, etd.grBinds); + auto *compInst = ECS_CreateInstance(genericEntity, uuid, etd.grBinds, nullptr); btVector3 scaling{1.f,1.f,1.f}; btTransform posRot{}; @@ -65,17 +65,18 @@ Entity_Base *EntityType_CreateGenericInstance(EntityType *et, Entity_Base *level } compInst->physicsLayer = srcInstance->physicsLayer; compInst->physicsMask = srcInstance->physicsMask; - posRot = instPos->posRot; } else { compInst->physicsLayer = etd.bt.startingCollisionLayer; compInst->physicsMask = etd.bt.startingCollisionMask; posRot.setIdentity(); } if (instPos != nullptr) { + posRot = instPos->posRot; mass = instPos->mass; scaling = instPos->scale; } else { mass = etd.bt.startingMass; + posRot.setIdentity(); } btVector3 localInertia(0, 0, 0); diff --git a/src/serialization-camera.cpp b/src/serialization-camera.cpp index 963853e..d6563b7 100644 --- a/src/serialization-camera.cpp +++ b/src/serialization-camera.cpp @@ -26,6 +26,15 @@ pk_handle pke_serialize_camera(srlztn_serialize_helper *h, const PkeCamera *cam) glm::quat quat_rot; glm::vec3 glm_scale; + kvec.type_code = cstring_to_pk_cstr(SRLZTN_OBJ_CAMERA); + kvec.bkt = h->bkt; + kvec.arr.bkt = h->bkt; + kvec.children.bkt = h->bkt; + kvec.child_handles.bkt = h->bkt; + pk_arr_reset(&kvec.arr); + pk_arr_reset(&kvec.children); + pk_arr_reset(&kvec.child_handles); + if (PK_HAS_FLAG(cam->entity_flags, ENTITY_FLAG_DO_NOT_SERIALIZE)) { return PK_HANDLE_MAX; } @@ -44,13 +53,8 @@ pk_handle pke_serialize_camera(srlztn_serialize_helper *h, const PkeCamera *cam) inst_pos_handle = pke_serialize_inst_pos(h, glm_pos, quat_rot, glm_scale); kvec.srlztn_handle = h->handle_head; - kvec.type_code = cstring_to_pk_cstr(SRLZTN_OBJ_CAMERA); - kvec.bkt = h->bkt; - kvec.arr.bkt = h->bkt; - kvec.children.bkt = h->bkt; - kvec.child_handles.bkt = h->bkt; h->handle_head.itemIndex++; - pk_arr_append_t(&kvec.child_handles, inst_pos_handle); + pk_arr_append_t<pk_handle>(&kvec.child_handles, inst_pos_handle); if (cam->uuid != pk_uuid_zed && cam->uuid != pk_uuid_max) { kve.key = SRLZTN_CAMERA_UUID; @@ -94,6 +98,9 @@ pk_handle pke_serialize_camera(srlztn_serialize_helper *h, const PkeCamera *cam) } pk_arr_append_t(&h->kvp_containers, kvec); + kvec.arr.data = nullptr; + kvec.children.data = nullptr; + kvec.child_handles.data = nullptr; return kvec.srlztn_handle; } @@ -120,37 +127,6 @@ void pke_deserialize_camera(srlztn_deserialize_helper *h, pke_kve_container *kve } for (i = 0; i < kvec->arr.next; ++i) { - if (strcmp(kvec->arr[i].key, SRLZTN_OBJ_END) == 0) { - - uint32_t targetInstanceIndex = -1; - if (target_uuid != pk_uuid_zed) { - targetInstanceIndex = pk_arr_find_first_index(&h->mapping, &target_uuid, srlztn_mapping_find_first_handle_by_uuid); - if (targetInstanceIndex == uint32_t(-1)) { - fprintf(stderr, "[pke_deserialize_camera] Camera has target instance uuid '" pk_uuid_printf_format "', but failed to find target instance.", pk_uuid_printf_var(target_uuid)); - } - } - - btVector3 bt_pos; - btQuaternion bt_rot; - GlmToBullet(pos, bt_pos); - GlmToBullet(scale, instPos.scale); - GlmToBullet(quat_rot, bt_rot); - instPos.posRot.setOrigin(bt_pos); - instPos.posRot.setRotation(bt_rot); - auto &rCam = PkeCamera_Register(cam.uuid, instPos); - rCam.type = cam.type; - rCam.view = cam.view; - rCam.isPrimary = cam.isPrimary; - pke_scene_register_camera(h->scene->scene_handle, rCam.camHandle); - if (targetInstanceIndex != uint32_t(-1)) { - rCam.phys.target_inst_handle = h->mapping[targetInstanceIndex].created_instance->instanceHandle; - PkeCamera_TargetInstance(rCam.camHandle, h->mapping[targetInstanceIndex].created_instance); - } - if (rCam.isPrimary == true) { - ActiveCamera = &rCam; - } - return; - } if (strncmp(kvec->arr[i].key, SRLZTN_CAMERA_UUID, strlen(SRLZTN_CAMERA_TYPE)) == 0) { kvec->arr[i].val >> cam.uuid; continue; @@ -185,5 +161,33 @@ void pke_deserialize_camera(srlztn_deserialize_helper *h, pke_kve_container *kve continue; } } + + uint32_t targetInstanceIndex = -1; + if (target_uuid != pk_uuid_zed) { + targetInstanceIndex = pk_arr_find_first_index(&h->mapping, &target_uuid, srlztn_mapping_find_first_handle_by_uuid); + if (targetInstanceIndex == uint32_t(-1)) { + fprintf(stderr, "[pke_deserialize_camera] Camera has target instance uuid '" pk_uuid_printf_format "', but failed to find target instance.", pk_uuid_printf_var(target_uuid)); + } + } + + btVector3 bt_pos; + btQuaternion bt_rot; + GlmToBullet(pos, bt_pos); + GlmToBullet(scale, instPos.scale); + GlmToBullet(quat_rot, bt_rot); + instPos.posRot.setOrigin(bt_pos); + instPos.posRot.setRotation(bt_rot); + auto &rCam = PkeCamera_Register(cam.uuid, instPos); + rCam.type = cam.type; + rCam.view = cam.view; + rCam.isPrimary = cam.isPrimary; + pke_scene_register_camera(h->scene->scene_handle, rCam.camHandle); + if (targetInstanceIndex != uint32_t(-1)) { + rCam.phys.target_inst_handle = h->mapping[targetInstanceIndex].created_instance->instanceHandle; + PkeCamera_TargetInstance(rCam.camHandle, h->mapping[targetInstanceIndex].created_instance); + } + if (rCam.isPrimary == true) { + ActiveCamera = &rCam; + } return; } diff --git a/src/serialization-component.cpp b/src/serialization-component.cpp index 7514a14..afa3b89 100644 --- a/src/serialization-component.cpp +++ b/src/serialization-component.cpp @@ -50,6 +50,12 @@ pk_handle pke_serialize_inst_pos(srlztn_serialize_helper *h, const glm::vec3 pos pk_arr_append_t(&kvec.arr, kve); } pk_arr_append_t(&h->kvp_containers, kvec); + // 2025-05-08 JCB + // this is dead code, but it's here as a reminder to not call pk_arr_reset + // so that the underlying data is not freed. + kvec.child_handles.data = nullptr; + kvec.children.data = nullptr; + kvec.arr.data = nullptr; return kvec.srlztn_handle; } @@ -58,10 +64,12 @@ void pke_deserialize_inst_pos(srlztn_deserialize_helper *h, pke_kve_container *k char *pEnd = nullptr; uint32_t i, index; const char *starting_char; + pke_kve *kve; PK_STN_RES stn_res; for (i = 0; i < kvec->arr.next; ++i) { - if (strstr(kvec->arr[i].key, SRLZTN_POSROT_POS)) { - starting_char = kvec->arr[i].val; + kve = &kvec->arr[i]; + if (strstr(kve->key, SRLZTN_POSROT_POS)) { + starting_char = kve->val; index = 0; do { assert(index < 3); @@ -70,9 +78,10 @@ void pke_deserialize_inst_pos(srlztn_deserialize_helper *h, pke_kve_container *k starting_char = pEnd + 1; ++index; } while (*pEnd != '\0'); + continue; } - if (strstr(kvec->arr[i].key, SRLZTN_POSROT_ROT)) { - starting_char = kvec->arr[i].val; + if (strstr(kve->key, SRLZTN_POSROT_ROT)) { + starting_char = kve->val; index = 0; do { assert(index < 4); @@ -81,9 +90,10 @@ void pke_deserialize_inst_pos(srlztn_deserialize_helper *h, pke_kve_container *k starting_char = pEnd + 1; ++index; } while (*pEnd != '\0'); + continue; } - if (strstr(kvec->arr[i].key, SRLZTN_POSROT_SCALE)) { - starting_char = kvec->arr[i].val; + if (strstr(kve->key, SRLZTN_POSROT_SCALE)) { + starting_char = kve->val; index = 0; do { assert(index < 3); @@ -92,6 +102,7 @@ void pke_deserialize_inst_pos(srlztn_deserialize_helper *h, pke_kve_container *k starting_char = pEnd + 1; ++index; } while (*pEnd != '\0'); + continue; } } } @@ -103,10 +114,9 @@ pk_handle pke_serialize_instance(srlztn_serialize_helper *h, const CompInstance pk_handle inst_pos_handle; pke_kve kve{}; pke_kve_container kvec{}; - CompInstance c{}; - glm::vec3 pos; - glm::quat quat_rot; - glm::vec3 scale; + glm::vec3 pos = glm::vec3(0,0,0); + glm::quat quat_rot = glm::quat(1,0,0,0); + glm::vec3 scale = glm::vec3(1,1,1); float mass; PhysicsCollision collisionLayer; PhysicsCollision collisionMask; @@ -120,7 +130,12 @@ pk_handle pke_serialize_instance(srlztn_serialize_helper *h, const CompInstance comp->bt.motionState->getWorldTransform(trans); BulletToGlm(trans.getOrigin(), pos); BulletToGlm(trans.getRotation(), quat_rot); - BulletToGlm(comp->bt.rigidBody->getCollisionShape()->getLocalScaling(), scale); + if (comp->bt.rigidBody != nullptr) { + auto a1 = comp->bt.rigidBody; + auto a2 = a1 != nullptr ? a1->getCollisionShape() : nullptr; + auto a3 = a2 != nullptr ? a2->getLocalScaling() : btVector3(1,1,1); + BulletToGlm(a3, scale); + } } inst_pos_handle = pke_serialize_inst_pos(h, pos, quat_rot, scale); @@ -154,7 +169,7 @@ pk_handle pke_serialize_instance(srlztn_serialize_helper *h, const CompInstance kve.end = SRLZTN_KVE_END; pk_arr_append_t(&kvec.arr, kve); } - if (mass != 1) { + { kve.key = SRLZTN_INSTANCE_COMPONENT_MASS; len = snprintf(NULL, 0, "%f", mass); s = pk_new<char>(len+1, h->bkt); @@ -163,20 +178,20 @@ pk_handle pke_serialize_instance(srlztn_serialize_helper *h, const CompInstance kve.end = SRLZTN_KVE_END; pk_arr_append_t(&kvec.arr, kve); } - if (collisionLayer != c.physicsLayer) { + { kve.key = SRLZTN_INSTANCE_COMPONENT_COLLISION_LAYER; - len = snprintf(NULL, 0, "%lu", static_cast<PhysicsCollision_T>(collisionLayer)); + len = snprintf(NULL, 0, "0x%.016lX", static_cast<PhysicsCollision_T>(collisionLayer)); s = pk_new<char>(len+1, h->bkt); - sprintf(s, "%lu", static_cast<PhysicsCollision_T>(collisionLayer)); + sprintf(s, "0x%.016lX", static_cast<PhysicsCollision_T>(collisionLayer)); kve.val = s; kve.end = SRLZTN_KVE_END; pk_arr_append_t(&kvec.arr, kve); } - if (collisionMask != c.physicsMask) { + { kve.key = SRLZTN_INSTANCE_COMPONENT_COLLISION_MASK; - len = snprintf(NULL, 0, "%lu", static_cast<PhysicsCollision_T>(collisionMask)); + len = snprintf(NULL, 0, "0x%.016lX", static_cast<PhysicsCollision_T>(collisionMask)); s = pk_new<char>(len+1, h->bkt); - sprintf(s, "%lu", static_cast<PhysicsCollision_T>(collisionMask)); + sprintf(s, "0x%.016lX", static_cast<PhysicsCollision_T>(collisionMask)); kve.val = s; kve.end = SRLZTN_KVE_END; pk_arr_append_t(&kvec.arr, kve); @@ -214,53 +229,6 @@ void pke_deserialize_instance(srlztn_deserialize_helper *h, pke_kve_container *k } for (i = 0; i < kvec->arr.next; ++i) { - if (strstr(SRLZTN_OBJ_END, kvec->arr[i].key)) { - if (et_ptr == nullptr) { - fprintf(stdout, "[Game::DeserializeInstance] Unknown EntityTypeCode, skipping instance.\n"); - break; - } - btVector3 bt_pos; - btQuaternion bt_quat; - GlmToBullet(pos, bt_pos); - GlmToBullet(quat_rot, bt_quat); - GlmToBullet(scale, inst_pos.scale); - inst_pos.mass = mass; - inst_pos.posRot.setIdentity(); - inst_pos.posRot.setOrigin(bt_pos); - inst_pos.posRot.setRotation(bt_quat); - if (et_ptr->createInstanceCallback.func != nullptr) { - /* TODO 2025-03-27 JCB - * We have not yet defined what the appropriate callback signature - * for creating an entity instance is. - * What should be passed as arguments? What would need to be passed - * that couldn't be accessed globally? - * Consider changing this callback to trigger after creating a - * generic instance, rather than *creating* it. - * Also consider just requiring a generic instance for any given - * EntityType. - */ - // typedef Entity_Base *CreateInst(); - // entity = reinterpret_cast<CreateInst*>(et_ptr->createInstanceCallback.func)(); - fprintf(stderr, "[%s] Attempted to call EntityType::createInstanceCallback and we have not yet defined a valid function signature", __FILE__); - } else { - srlztn_instance_mapping map{}; - map.serialized_uuid = comp.uuid; - map.created_entity = EntityType_CreateGenericInstance(et_ptr, h->scene, &comp, &inst_pos); - // TODO gross - pk_arr_t<CompInstance *> instances; - ECS_GetInstances(map.created_entity, instances); - for (uint32_t i = 0; i < instances.next; ++i) { - if (comp.uuid == instances[i]->uuid) { - map.created_instance = instances[i]; - } - } - if (map.created_instance == nullptr) { - fprintf(stderr, "[pke_deserialize_instance] Failed to find created instance for creating mapping"); - } else { - pk_arr_append(&h->mapping, &map); - } - } - } if (strstr(kvec->arr[i].key, SRLZTN_INSTANCE_COMPONENT_UUID)) { kvec->arr[i].val >> comp.uuid ; continue; @@ -295,5 +263,54 @@ void pke_deserialize_instance(srlztn_deserialize_helper *h, pke_kve_container *k continue; } } + if (et_ptr == nullptr) { + fprintf(stdout, "[Game::DeserializeInstance] Unknown EntityTypeCode, skipping instance.\n"); + } + btVector3 bt_pos; + btQuaternion bt_quat; + GlmToBullet(pos, bt_pos); + GlmToBullet(quat_rot, bt_quat); + GlmToBullet(scale, inst_pos.scale); + inst_pos.mass = mass; + inst_pos.posRot.setIdentity(); + inst_pos.posRot.setOrigin(bt_pos); + inst_pos.posRot.setRotation(bt_quat); + pk_arr_t<CompInstance *> instances; + srlztn_instance_mapping map{}; + map.serialized_uuid = comp.uuid; + if (et_ptr != nullptr) { + if (et_ptr->createInstanceCallback.func != nullptr) { + /* TODO 2025-03-27 JCB + * We have not yet defined what the appropriate callback signature + * for creating an entity instance is. + * What should be passed as arguments? What would need to be passed + * that couldn't be accessed globally? + * Consider changing this callback to trigger after creating a + * generic instance, rather than *creating* it. + * Also consider just requiring a generic instance for any given + * EntityType. + */ + // typedef Entity_Base *CreateInst(); + // entity = reinterpret_cast<CreateInst*>(et_ptr->createInstanceCallback.func)(); + fprintf(stderr, "[%s] Attempted to call EntityType::createInstanceCallback and we have not yet defined a valid function signature", __FILE__); + } else { + map.created_entity = EntityType_CreateGenericInstance(et_ptr, h->scene, &comp, &inst_pos); + } + } else { + map.created_entity = ECS_CreateGenericEntity(); + map.created_instance = ECS_CreateInstance(map.created_entity, comp.uuid, nullptr, &inst_pos); + } + ECS_GetInstances(map.created_entity, instances); + for (uint32_t i = 0; i < instances.next; ++i) { + if (comp.uuid == instances[i]->uuid) { + map.created_instance = instances[i]; + } + } + pk_arr_reset(&instances); + if (map.created_instance == nullptr) { + fprintf(stderr, "[pke_deserialize_instance] Failed to find created instance for creating mapping"); + } else { + pk_arr_append(&h->mapping, &map); + } return; } diff --git a/src/serialization.cpp b/src/serialization.cpp index bc5fb44..ce2dbd3 100644 --- a/src/serialization.cpp +++ b/src/serialization.cpp @@ -17,20 +17,22 @@ bool srlztn_kvec_find_first_by_handle(void *handle, void *container) { srlztn_serialize_helper *pke_serialize_init(pk_membucket *bkt) { srlztn_serialize_helper *helper = pk_new<srlztn_serialize_helper>(bkt); - // TODO custom allocator - // helper->o = {}; helper->bkt = bkt; helper->kvp_containers.bkt = bkt; + pk_arr_reserve(&helper->kvp_containers, 1); + pk_arr_reset(&helper->kvp_containers); return helper; } srlztn_deserialize_helper *pke_deserialize_init(pk_membucket *bkt) { srlztn_deserialize_helper *helper = pk_new<srlztn_deserialize_helper>(bkt); helper->bkt = bkt; - // helper->read_line = nullptr; - // TODO custom allocator - // helper->mapping = {bkt}; helper->kvp_containers.bkt = bkt; + helper->mapping.bkt = bkt; + pk_arr_reset(&helper->kvp_containers); + pk_arr_reset(&helper->mapping); + pk_arr_reserve(&helper->kvp_containers, 1); + pk_arr_reserve(&helper->mapping, 1); return helper; } @@ -58,28 +60,19 @@ void pke_deserialize_project_from_stream(std::istream &i, srlztn_deserialize_hel } void pke_serialize_scene(srlztn_serialize_helper *h) { - pke_kve_container kvec = {}; - kvec.bkt = h->bkt; - kvec.arr.bkt = h->bkt; - kvec.children.bkt = h->bkt; - kvec.type_code = cstring_to_pk_cstr(SRLZTN_OBJ_INSTANCE); pk_handle_bucket_index_T instanceBucketCount = ECS_GetInstances_BucketCount(); for (pk_handle_bucket_index_T b = 0; b < instanceBucketCount; ++b) { pk_handle_item_index_T count; auto *instances = ECS_GetInstances(b, count); for (pk_handle_item_index_T i = 0; i < count; ++i) { const auto &instance = instances[i]; - if (instance.entHandle == EntityHandle_MAX) - continue; if (PK_HAS_FLAG(instance.comp_instance_flags, COMPONENT_INSTANCE_FLAG_DO_NOT_SERIALIZE)) { continue; } pke_serialize_instance(h, &instance); - pk_arr_append_t(&h->kvp_containers, kvec); } } - kvec.type_code = cstring_to_pk_cstr(SRLZTN_OBJ_CAMERA); pk_handle_bucket_index_T cameraBucketCount = PkeCamera_GetBucketCount(); for (pk_handle_bucket_index_T b = 0; b < cameraBucketCount; ++b) { pk_handle_item_index_T count; @@ -89,7 +82,6 @@ void pke_serialize_scene(srlztn_serialize_helper *h) { if (cam.handle == CameraHandle_MAX) continue; pke_serialize_camera(h, &cam); - pk_arr_append_t(&h->kvp_containers, kvec); } } } @@ -99,11 +91,11 @@ void pke_deserialize_scene(srlztn_deserialize_helper *h) { for (i = 0; i < h->kvp_containers.next; ++i) { kvec = &h->kvp_containers[i]; - if (strcmp(SRLZTN_OBJ_INSTANCE, kvec->type_code.val) == 0) { + if (strstr(kvec->type_code.val, SRLZTN_OBJ_INSTANCE) != nullptr) { pke_deserialize_instance(h, kvec); continue; } - if (strcmp(SRLZTN_OBJ_CAMERA, kvec->type_code.val) == 0) { + if (strstr(kvec->type_code.val, SRLZTN_OBJ_CAMERA) != nullptr) { pke_deserialize_camera(h, kvec); continue; } @@ -120,16 +112,16 @@ void pke_serialize_scene_to_stream(std::ostream &o, srlztn_serialize_helper *h) for (i = 0; i < h->kvp_containers.next; ++i) { kvec = &h->kvp_containers[i]; - o << kvec->type_code.val; + o << kvec->type_code.val << ":"; o << std::setw(8) << std::setfill('0') << std::setbase(16) << kvec->srlztn_handle.bucketIndex; o << SRLZTN_HANDLE_SEPARATOR; o << std::setw(8) << std::setfill('0') << std::setbase(16) << kvec->srlztn_handle.itemIndex; o << std::setbase(0) << std::setw(0) << std::endl; for (k = 0; k < kvec->child_handles.next; ++k) { o << SRLZTN_CHILD_ID; - o << std::setw(8) << std::setfill('0') << std::setbase(16) << kvec->srlztn_handle.bucketIndex; + o << std::setw(8) << std::setfill('0') << std::setbase(16) << kvec->child_handles[k].bucketIndex; o << SRLZTN_HANDLE_SEPARATOR; - o << std::setw(8) << std::setfill('0') << std::setbase(16) << kvec->srlztn_handle.itemIndex; + o << std::setw(8) << std::setfill('0') << std::setbase(16) << kvec->child_handles[k].itemIndex; o << std::setbase(0) << std::setw(0) << std::endl; } for (k = 0; k < kvec->arr.next; ++k) { @@ -139,7 +131,7 @@ void pke_serialize_scene_to_stream(std::ostream &o, srlztn_serialize_helper *h) o << SRLZTN_OBJ_END << std::endl; } - o << SRLZTN_FILE_END << std::endl; + o << SRLZTN_FILE_END; } void pke_deserialize_scene_from_stream(std::istream &i, srlztn_deserialize_helper *h) { // 0: new object @@ -159,6 +151,7 @@ void pke_deserialize_scene_from_stream(std::istream &i, srlztn_deserialize_helpe kvec.bkt = h->bkt; kvec.arr.bkt = h->bkt; kvec.children.bkt = h->bkt; + kvec.child_handles.bkt = h->bkt; i.getline(read_line, read_line_len); assert(strstr(read_line, SRLZTN_FILE_BEGIN) != 0); @@ -248,8 +241,15 @@ void pke_deserialize_scene_from_stream(std::istream &i, srlztn_deserialize_helpe kvec.type_code.val = nullptr; kvec.type_code.length = 0; kvec.type_code.reserved = 0; - pk_arr_reset(&kvec.arr); - pk_arr_reset(&kvec.children); + kvec.children.next = 0; + kvec.children.reserved = 0; + kvec.children.data = nullptr; + kvec.arr.next = 0; + kvec.arr.reserved = 0; + kvec.arr.data = nullptr; + kvec.child_handles.next = 0; + kvec.child_handles.reserved = 0; + kvec.child_handles.data = nullptr; } } @@ -269,6 +269,9 @@ void pke_deserialize_scene_from_stream(std::istream &i, srlztn_deserialize_helpe } } + kvec.arr.data = nullptr; + kvec.children.data = nullptr; + kvec.child_handles.data = nullptr; pk_delete<char>(read_line, read_line_len, h->bkt); } diff --git a/src/serialization.hpp b/src/serialization.hpp index 3b74428..93fd92a 100644 --- a/src/serialization.hpp +++ b/src/serialization.hpp @@ -19,13 +19,13 @@ iccsc SRLZTN_MULTILINE_END = ":MULTILINE_END:"; iccsc SRLZTN_CHILD_ID = "ChildId:"; iccsc SRLZTN_OBJ_END = ""; -iccsc SRLZTN_OBJ_INSTANCE_POSITION = "InstPos:"; -iccsc SRLZTN_OBJ_INSTANCE = "Instance:"; -iccsc SRLZTN_OBJ_CAMERA = "Camera:"; -iccsc SRLZTN_OBJ_UI_BOX = "UIBox:"; -iccsc SRLZTN_OBJ_FONT_RENDER = "FontRender:"; -iccsc SRLZTN_OBJ_FONT_RENDER_SETTINGS = "FontRenderSettings:"; -iccsc SRLZTN_OBJ_UI_BOX_TYPE_DATA = "UIBoxTypeData:"; +iccsc SRLZTN_OBJ_INSTANCE_POSITION = "InstPos"; +iccsc SRLZTN_OBJ_INSTANCE = "Instance"; +iccsc SRLZTN_OBJ_CAMERA = "Camera"; +iccsc SRLZTN_OBJ_UI_BOX = "UIBox"; +iccsc SRLZTN_OBJ_FONT_RENDER = "FontRender"; +iccsc SRLZTN_OBJ_FONT_RENDER_SETTINGS = "FontRenderSettings"; +iccsc SRLZTN_OBJ_UI_BOX_TYPE_DATA = "UIBoxTypeData"; iccsc SRLZTN_POSROT_POS = "Position:"; iccsc SRLZTN_POSROT_ROT = "Rotation:"; @@ -78,17 +78,13 @@ struct srlztn_instance_mapping { struct srlztn_serialize_helper { pk_membucket *bkt; - // std::ostringstream o; pk_arr_t<pke_kve_container> kvp_containers; pk_handle handle_head; }; struct srlztn_deserialize_helper { pk_membucket *bkt; - // std::istream *i; - // size_t read_line_len = 256; pke_scene *scene; - // char *read_line; pk_arr_t<srlztn_instance_mapping> mapping; pk_arr_t<pke_kve_container> kvp_containers; }; diff --git a/tests/pke-test-serialization.cpp b/tests/pke-test-serialization.cpp index 64523d8..c514578 100644 --- a/tests/pke-test-serialization.cpp +++ b/tests/pke-test-serialization.cpp @@ -1,14 +1,85 @@ #include "./pke-test-serialization.h" +#include "game-settings.hpp" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" +#include "camera.hpp" +#include "ecs.hpp" +#include "physics.hpp" #include "pk.h" +#include "scene.hpp" +#include "serialization-camera.hpp" #include "serialization-component.hpp" #include "serialization.hpp" #include <cstring> #include <sstream> -pk_membucket *bkt; +pk_membucket *bkt = nullptr; +const char *test_scene_name = "srlztn_test_scene"; +pke_scene *test_scene = nullptr; + +void pke_test_serialization_spinup() { + pkeSettings.isSimulationPaused = true; + Physics_Init(); + ECS_Init(); + PkeCamera_Init(); + pke_scene_master_init(); + test_scene = pke_scene_create(test_scene_name); +}; + +void pke_test_serialization_teardown() { + // pke_scene_remove(test_scene->scene_handle); // TODO this doesn't work? + test_scene = nullptr; + pke_scene_master_teardown(); + PkeCamera_Teardown(); + ECS_Teardown(); + Physics_Teardown(); +}; + +int pke_test_serialization_999() { + int64_t err_index = 0; + pke_kve_container kvec{}; + pke_kve kve{}; + const pk_handle zed_handle = {0,0}; + PKE_TEST_ASSERT(kvec.srlztn_handle == zed_handle, err_index); + + PKE_TEST_ASSERT(kvec.type_code.length == 0, err_index); + PKE_TEST_ASSERT(kvec.type_code.reserved == 0, err_index); + PKE_TEST_ASSERT(kvec.type_code.val == nullptr, err_index); + + PKE_TEST_ASSERT(kvec.bkt == nullptr, err_index); + + // 6 + PKE_TEST_ASSERT(kvec.child_handles.next == 0, err_index); + PKE_TEST_ASSERT(kvec.child_handles.reserved == 0, err_index); + PKE_TEST_ASSERT(kvec.child_handles.stride == sizeof(pk_handle), err_index); + PKE_TEST_ASSERT(kvec.child_handles.alignment == alignof(pk_handle), err_index); + PKE_TEST_ASSERT(kvec.child_handles.bkt == nullptr, err_index); + PKE_TEST_ASSERT(kvec.child_handles.data == nullptr, err_index); + + // 12 + PKE_TEST_ASSERT(kvec.children.next == 0, err_index); + PKE_TEST_ASSERT(kvec.children.reserved == 0, err_index); + PKE_TEST_ASSERT(kvec.children.stride == sizeof(pke_kve_container*), err_index); + PKE_TEST_ASSERT(kvec.children.alignment == alignof(pke_kve_container*), err_index); + PKE_TEST_ASSERT(kvec.children.bkt == nullptr, err_index); + PKE_TEST_ASSERT(kvec.children.data == nullptr, err_index); + + // 18 + PKE_TEST_ASSERT(kvec.arr.next == 0, err_index); + PKE_TEST_ASSERT(kvec.arr.reserved == 0, err_index); + PKE_TEST_ASSERT(kvec.arr.stride == sizeof(pke_kve), err_index); + PKE_TEST_ASSERT(kvec.arr.alignment == alignof(pke_kve), err_index); + PKE_TEST_ASSERT(kvec.arr.bkt == nullptr, err_index); + PKE_TEST_ASSERT(kvec.arr.data == nullptr, err_index); + + // 24 + PKE_TEST_ASSERT(kve.key == nullptr, err_index); + PKE_TEST_ASSERT(kve.val == nullptr, err_index); + PKE_TEST_ASSERT(kve.end == nullptr, err_index); + return 0; +} const char *const test_001_str = R"VOGON(:PKFB: :0: @@ -18,8 +89,7 @@ Position:0.000000;1.000000;2.000000 Rotation:7.000000;8.000000;9.000000;6.000000 Scale:5.000000;4.000000;3.000000 -:PKFE: -)VOGON"; +:PKFE:)VOGON"; int pke_test_serialization_001() { int64_t err_index = 0, i; srlztn_serialize_helper *h; @@ -103,10 +173,192 @@ int pke_test_deserialization_101() { return 0; } +const char *const test_002_str = R"VOGON(:PKFB: +:0: + +InstPos:00000000!00000000 +Rotation:0.000000;0.000000;0.000000;1.000000 + +Instance:00000000!00000001 +ChildId:00000000!00000000 +UUID:67eec271-ab64-78d2-a38e-1f2946e87ccd +Mass:1.000000 +CollisionLayer:0x0000000000000001 +CollisionMask:0x0000000000000001 + +InstPos:00000000!00000002 +Position:0.000000;-10.000000;-10.000000 +Rotation:0.000000;0.000000;0.000000;1.000000 +Scale:5.000000;4.000000;3.000000 + +Camera:00000000!00000003 +ChildId:00000000!00000002 +UUID:67eec26e-56c4-7aeb-a43c-986966334873 +Type:0x01 +Orientation:0x01 +TargetUUID:67eec271-ab64-78d2-a38e-1f2946e87ccd +IsPrimary:1 + +:PKFE:)VOGON"; +int pke_test_serialization_002() { + int64_t err_index = 0; + uint32_t i, k; + srlztn_serialize_helper *h = nullptr; + pke_kve *kve = nullptr; + std::stringstream ss; + try { + bkt = pk_bucket_create("pke_test_serialization", PK_DEFAULT_BUCKET_SIZE, false); + h = pke_serialize_init(bkt); + const pk_uuid camera_uuid = { .uuid = { 0x67,0xEE,0xC2,0x6E,0x56,0xC4,0x7A,0xEB,0xA4,0x3C,0x98,0x69,0x66,0x33,0x48,0x73 } }; + const pk_uuid target_uuid = { .uuid = { 0x67,0xEE,0xC2,0x71,0xAB,0x64,0x78,0xD2,0xA3,0x8E,0x1F,0x29,0x46,0xE8,0x7C,0xCD } }; + + // reminder that 'targeting' moves and rotates the camera, so we shouldn't see these values in the output + InstPos cam_inst_pos{}; + cam_inst_pos.posRot.setIdentity(); + cam_inst_pos.posRot.setOrigin(btVector3(0,0,0)); + cam_inst_pos.posRot.setRotation(btQuaternion(0.f,0.f,0.f,1)); + cam_inst_pos.scale = btVector3(1,1,1); + cam_inst_pos.mass = 1.f; + + Entity_Base *target_ent = ECS_CreateGenericEntity(); + CompInstance *target_ent_comp_inst = ECS_CreateInstance(target_ent, target_uuid, nullptr, &cam_inst_pos); + + cam_inst_pos.scale = btVector3(5,4,3); + PkeCamera &cam = PkeCamera_Register(camera_uuid, cam_inst_pos); + cam.type = PKE_CAMERA_TYPE_PERSPECTIVE; + cam.view = PKE_CAMERA_VIEW_TARGET; + PkeCamera_SetPrimary(cam.camHandle); + PkeCamera_TargetInstance(cam.camHandle, target_ent_comp_inst); + + pke_serialize_scene(h); + pke_serialize_scene_to_stream(ss, h); + std::string s = ss.str(); + + PKE_TEST_ASSERT(h->bkt == bkt, err_index); + PKE_TEST_ASSERT(h->kvp_containers.bkt == bkt, err_index); + PKE_TEST_ASSERT(h->kvp_containers.next == 4, err_index); + // instpos + PKE_TEST_ASSERT(h->kvp_containers[0].child_handles.next == 0, err_index); + PKE_TEST_ASSERT(h->kvp_containers[0].arr.next == 1, err_index); + // instance + PKE_TEST_ASSERT(h->kvp_containers[1].child_handles.next == 1, err_index); + PKE_TEST_ASSERT(h->kvp_containers[1].arr.next == 4, err_index); + // instpos + PKE_TEST_ASSERT(h->kvp_containers[2].child_handles.next == 0, err_index); + PKE_TEST_ASSERT(h->kvp_containers[2].arr.next == 3, err_index); + // camera + PKE_TEST_ASSERT(h->kvp_containers[3].child_handles.next == 1, err_index); + PKE_TEST_ASSERT(h->kvp_containers[3].arr.next == 5, err_index); + + // 12 + for (k = 0; k < h->kvp_containers.next; ++k) { + for (i = 0; i < h->kvp_containers[k].arr.next; ++i) { + // 12 + (3 * (1 + 4 + 3 + 5)) + kve = &h->kvp_containers[k].arr[i]; + PKE_TEST_ASSERT(kve->key != nullptr, err_index); + PKE_TEST_ASSERT(kve->val != nullptr, err_index); + PKE_TEST_ASSERT(kve->end != nullptr, err_index); + } + } + + // 51 + PKE_TEST_ASSERT(strstr(test_002_str, s.c_str()) != nullptr, err_index); + + pke_serialize_teardown(h); + + } catch (const std::exception &ex) { + pk_bucket_destroy(bkt); + throw; + } + pk_bucket_destroy(bkt); + return 0; +} + +int pke_test_deserialization_102() { + int64_t err_index = 0; + uint32_t i, k; + pke_kve *kve; + srlztn_deserialize_helper *h; + std::stringstream ss(test_002_str); + try { + bkt = pk_bucket_create("pke_test_serialization", PK_DEFAULT_BUCKET_SIZE, false); + h = pke_deserialize_init(bkt); + h->scene = test_scene; + const pk_uuid camera_uuid = { .uuid = { 0x67,0xEE,0xC2,0x6E,0x56,0xC4,0x7A,0xEB,0xA4,0x3C,0x98,0x69,0x66,0x33,0x48,0x73 } }; + const pk_uuid target_uuid = { .uuid = { 0x67,0xEE,0xC2,0x71,0xAB,0x64,0x78,0xD2,0xA3,0x8E,0x1F,0x29,0x46,0xE8,0x7C,0xCD } }; + + pke_deserialize_scene_from_stream(ss, h); + + PKE_TEST_ASSERT(h->bkt == bkt, err_index); + PKE_TEST_ASSERT(h->kvp_containers.bkt == bkt, err_index); + PKE_TEST_ASSERT(h->kvp_containers.next == 4, err_index); + PKE_TEST_ASSERT(h->kvp_containers[0].child_handles.next == 0, err_index); + PKE_TEST_ASSERT(h->kvp_containers[1].child_handles.next == 1, err_index); + PKE_TEST_ASSERT(h->kvp_containers[2].child_handles.next == 0, err_index); + PKE_TEST_ASSERT(h->kvp_containers[3].child_handles.next == 1, err_index); + PKE_TEST_ASSERT(h->kvp_containers[0].arr.next == 1, err_index); + PKE_TEST_ASSERT(h->kvp_containers[1].arr.next == 4, err_index); + PKE_TEST_ASSERT(h->kvp_containers[2].arr.next == 3, err_index); + PKE_TEST_ASSERT(h->kvp_containers[3].arr.next == 5, err_index); + + // 12 + for (k = 0; k < h->kvp_containers.next; ++k) { + for (i = 0; i < h->kvp_containers[k].arr.next; ++i) { + // 12 + (3 * (1 + 4 + 3 + 5)) + kve = &h->kvp_containers[k].arr[i]; + PKE_TEST_ASSERT(kve->key != nullptr, err_index); + PKE_TEST_ASSERT(kve->val != nullptr, err_index); + PKE_TEST_ASSERT(kve->end != nullptr, err_index); + } + } + + glm::vec3 pos = glm::vec3(0,0,0); + glm::quat rot = glm::quat(1,0,0,0); + glm::vec3 scale = glm::vec3(1,1,1); + + pke_deserialize_inst_pos(h, &h->kvp_containers[0], pos, rot, scale); + // 51 + PKE_TEST_ASSERT(pos == glm::vec3(0,0,0), err_index); + PKE_TEST_ASSERT(rot == glm::quat(1,0,0,0), err_index); + PKE_TEST_ASSERT(scale == glm::vec3(1,1,1), err_index); + + pke_deserialize_inst_pos(h, &h->kvp_containers[2], pos, rot, scale); + // 54 + PKE_TEST_ASSERT(pos == glm::vec3(0,-10,-10), err_index); + PKE_TEST_ASSERT(rot == glm::quat(1,0,0,0), err_index); + PKE_TEST_ASSERT(scale == glm::vec3(5,4,3), err_index); + + pke_deserialize_scene(h); + + pk_handle_item_index_T item_index; + PkeCamera *des_cam = &PkeCamera_GetCameras(0, item_index)[0]; + // 57 + PKE_TEST_ASSERT(des_cam != nullptr, err_index); + PKE_TEST_ASSERT(des_cam->uuid == camera_uuid, err_index); + PKE_TEST_ASSERT(des_cam->type == PKE_CAMERA_TYPE_PERSPECTIVE, err_index); + PKE_TEST_ASSERT(des_cam->view == PKE_CAMERA_VIEW_TARGET, err_index); + PKE_TEST_ASSERT(des_cam->phys.target_inst_uuid == target_uuid, err_index); + PKE_TEST_ASSERT(des_cam->isPrimary == true, err_index); + + pke_deserialize_teardown(h); + + } catch (const std::exception &ex) { + pk_bucket_destroy(bkt); + throw; + } + pk_bucket_destroy(bkt); + return 0; +} + struct pke_test_group *pke_test_serialization_get_group() { - static const uint64_t test_count = 2; + static const uint64_t test_count = 5; static struct pke_test tests[test_count] = { { + .title = "test 999", + .func = pke_test_serialization_999, + .expected_result = 0, + }, + { .title = "test 001", .func = pke_test_serialization_001, .expected_result = 0, @@ -116,9 +368,23 @@ struct pke_test_group *pke_test_serialization_get_group() { .func = pke_test_deserialization_101, .expected_result = 0, }, + { + .title = "test 002", + .func = pke_test_serialization_002, + .expected_result = 0, + }, + { + .title = "test 102", + .func = pke_test_deserialization_102, + .expected_result = 0, + }, }; static struct pke_test_group group = {}; group.title = "de/serialization"; + group.group_setup = nullptr; + group.group_teardown = nullptr; + group.test_setup = pke_test_serialization_spinup; + group.test_teardown = pke_test_serialization_teardown; group.n_tests = test_count; group.tests = &tests[0]; |
