#include "utilities/EngineSerializationUtilities.h" #include #include #include #include #include #include "bones/BoneAnimationList.h" #include "bones/Skeleton.h" #include "utilities/IOUtilities.h" #include "utilities/JSONParser.h" // TODO: Validation BoneAnimationList * BoneAnimationList_fromJSON(struct JSONNode * rootNode) { BoneAnimationList * self; self = BoneAnimationList_create(); BoneAnimationList_loadJSON(self, rootNode); return self; } void BoneAnimationList_loadJSON(BoneAnimationList * self, JSONNode * rootNode) { unsigned int nodeIndex; if (rootNode == NULL) { return; } self->numberOfSequences = rootNode->numberOfChildren; self->sequences = malloc(sizeof(BoneAnimationSequence *) * self->numberOfSequences); for (nodeIndex = 0; nodeIndex < rootNode->numberOfChildren; nodeIndex++) { if (!strcmp(rootNode->children[nodeIndex].key, "#include")) { JSONNode * node; node = jsonFromFile(worldPath(rootNode->children[nodeIndex].value.string)); if (node != NULL) { BoneAnimationList_loadJSON(self, node); JSONParser_freeNodeContents(node); free(node); } } else { self->sequences[nodeIndex] = BoneAnimationSequence_fromJSON(&rootNode->children[nodeIndex]); } } } struct BoneAnimationSequence_keyframe_boneTransform BoneAnimationSequence_keyframe_boneTransform_fromJSON(JSONNode * rootNode) { unsigned int nodeIndex; struct BoneAnimationSequence_keyframe_boneTransform boneTransform; boneTransform.boneID = Atom_fromString(rootNode->key); boneTransform.orientation = Quaternion_identity(); boneTransform.offset = Vector3_zero(); for (nodeIndex = 0; nodeIndex < rootNode->numberOfChildren; nodeIndex++) { if (!strcmp(rootNode->children[nodeIndex].key, "orientation")) { boneTransform.orientation = Quaternion_fromJSON(&rootNode->children[nodeIndex]); } else if (!strcmp(rootNode->children[nodeIndex].key, "offset")) { boneTransform.offset = Vector3_fromJSON(&rootNode->children[nodeIndex]); } } return boneTransform; } struct BoneAnimationSequence_keyframe BoneAnimationSequence_keyframe_fromJSON(JSONNode * rootNode) { unsigned int nodeIndex, boneIndex; struct BoneAnimationSequence_keyframe keyframe; keyframe.duration = 1.0f; keyframe.numberOfBones = 0; keyframe.boneTransforms = NULL; for (nodeIndex = 0; nodeIndex < rootNode->numberOfChildren; nodeIndex++) { if (!strcmp(rootNode->children[nodeIndex].key, "duration")) { keyframe.duration = rootNode->children[nodeIndex].value.number; } else if (!strcmp(rootNode->children[nodeIndex].key, "bone_transforms")) { keyframe.numberOfBones = rootNode->children[nodeIndex].numberOfChildren; keyframe.boneTransforms = malloc(sizeof(struct BoneAnimationSequence_keyframe_boneTransform) * keyframe.numberOfBones); for (boneIndex = 0; boneIndex < rootNode->children[nodeIndex].numberOfChildren; boneIndex++) { keyframe.boneTransforms[boneIndex] = BoneAnimationSequence_keyframe_boneTransform_fromJSON(&rootNode->children[nodeIndex].children[boneIndex]); } } } return keyframe; } BoneAnimationSequence * BoneAnimationSequence_fromJSON(JSONNode * rootNode) { BoneAnimationSequence * self; unsigned int nodeIndex; self = BoneAnimationSequence_create(Atom_fromString(rootNode->key), NULL); self->numberOfKeyframes = rootNode->numberOfChildren; self->keyframes = malloc(sizeof(struct BoneAnimationSequence_keyframe) * self->numberOfKeyframes); for (nodeIndex = 0; nodeIndex < rootNode->numberOfChildren; nodeIndex++) { self->keyframes[nodeIndex] = BoneAnimationSequence_keyframe_fromJSON(&rootNode->children[nodeIndex]); } return self; } Quaternion Quaternion_fromJSON(struct JSONNode * rootNode) { bool haveAxis = false, haveAngle = false; Vector3 axis = {0.0f, 0.0f, 0.0f}; float angle = 0.0f; unsigned int nodeIndex; Quaternion quaternion = {0.0f, 0.0f, 0.0f, 1.0f}; for (nodeIndex = 0; nodeIndex < rootNode->numberOfChildren; nodeIndex++) { if (!strcmp(rootNode->children[nodeIndex].key, "axis")) { axis = Vector3_fromJSON(&rootNode->children[nodeIndex]); if (haveAngle) { quaternion = Quaternion_fromAxisAngle(axis, angle); } haveAxis = true; } else if (!strcmp(rootNode->children[nodeIndex].key, "radians")) { angle = rootNode->children[nodeIndex].value.number; if (haveAxis) { quaternion = Quaternion_fromAxisAngle(axis, angle); } haveAngle = true; } else if (!strcmp(rootNode->children[nodeIndex].key, "degrees")) { angle = rootNode->children[nodeIndex].value.number * M_PI / 180.0f; if (haveAxis) { quaternion = Quaternion_fromAxisAngle(axis, angle); } haveAngle = true; } else if (!strcmp(rootNode->children[nodeIndex].key, "x")) { quaternion.x = rootNode->children[nodeIndex].value.number; } else if (!strcmp(rootNode->children[nodeIndex].key, "y")) { quaternion.y = rootNode->children[nodeIndex].value.number; } else if (!strcmp(rootNode->children[nodeIndex].key, "z")) { quaternion.z = rootNode->children[nodeIndex].value.number; } else if (!strcmp(rootNode->children[nodeIndex].key, "w")) { quaternion.w = rootNode->children[nodeIndex].value.number; } } return quaternion; } Skeleton * Skeleton_fromJSON(JSONNode * rootNode) { Skeleton * self; self = Skeleton_create(); Skeleton_loadJSON(self, rootNode); return self; } void Skeleton_loadJSON(Skeleton * self, JSONNode * rootNode) { unsigned int nodeIndex; unsigned int bonePropertyIndex; if (rootNode == NULL) { return; } self->numberOfBones = rootNode->numberOfChildren; self->bones = calloc(sizeof(struct Skeleton_bone), self->numberOfBones); for (nodeIndex = 0; nodeIndex < rootNode->numberOfChildren; nodeIndex++) { if (!strcmp(rootNode->children[nodeIndex].key, "#include")) { JSONNode * node; node = jsonFromFile(worldPath(rootNode->children[nodeIndex].value.string)); if (node != NULL) { Skeleton_loadJSON(self, node); JSONParser_freeNodeContents(node); free(node); } } else { self->bones[nodeIndex].boneID = Atom_fromString(rootNode->children[nodeIndex].key); for (bonePropertyIndex = 0; bonePropertyIndex < rootNode->children[nodeIndex].numberOfChildren; bonePropertyIndex++) { if (!strcmp(rootNode->children[nodeIndex].children[bonePropertyIndex].key, "parent")) { if (rootNode->children[nodeIndex].children[bonePropertyIndex].type == JSON_TYPE_NULL) { self->bones[nodeIndex].parentIndex = -1; } else { Atom parentID; unsigned int boneIndex; parentID = Atom_fromString(rootNode->children[nodeIndex].children[bonePropertyIndex].value.string); for (boneIndex = 0; boneIndex < nodeIndex; boneIndex++) { if (self->bones[boneIndex].boneID == parentID) { self->bones[nodeIndex].parentIndex = boneIndex; break; } } if (boneIndex == nodeIndex) { fprintf(stderr, "Warning: parent bone \"%s\" specified for bone \"%s\" not found\n", parentID, self->bones[nodeIndex].boneID); self->bones[nodeIndex].parentIndex = -1; } } } else if (!strcmp(rootNode->children[nodeIndex].children[bonePropertyIndex].key, "position")) { self->bones[nodeIndex].position = Vector3_fromJSON(&rootNode->children[nodeIndex].children[bonePropertyIndex]); } } } } } Vector3 Vector3_fromJSON(JSONNode * rootNode) { unsigned int nodeIndex; Vector3 vector = {0.0f, 0.0f, 0.0f}; for (nodeIndex = 0; nodeIndex < rootNode->numberOfChildren; nodeIndex++) { if (!strcmp(rootNode->children[nodeIndex].key, "x")) { vector.x = rootNode->children[nodeIndex].value.number; } else if (!strcmp(rootNode->children[nodeIndex].key, "y")) { vector.y = rootNode->children[nodeIndex].value.number; } else if (!strcmp(rootNode->children[nodeIndex].key, "z")) { vector.z = rootNode->children[nodeIndex].value.number; } } return vector; }