/// //Frees data allocated by an oct tree node // //Parameters: // tree: A pointer to the oct tree which the node being freed is apart of // node: A pointer to the oct tree node to free static void OctTree_Node_Free(OctTree* tree, struct OctTree_Node* node) { //If this node has children if(node->children != NULL) { for(int i = 0; i < 8; i++) { //Free the children! OctTree_Node_Free(tree, node->children + i); } //Free the children container... free(node->children); } else { //TODO: Figure out the proper way to deal with the freeing of the tree's hashmap. //Loop through the occupants of this list for(unsigned int i = 0; i < node->data->size; i++) { GObject* occupant = *(GObject**)DynamicArray_Index(node->data, i); //If the occupant still has a log in the hashmap if(HashMap_Contains(tree->map, &occupant, sizeof(GObject*))) { //Get the log of the occupant from the hashmap DynamicArray* log = (DynamicArray*)HashMap_LookUp(tree->map, &occupant, sizeof(GObject*))->data; //Find this node in the log struct OctTree_NodeStatus* status = NULL; for(unsigned int j = 0; j < log->size; j++) { status = (struct OctTree_NodeStatus*)DynamicArray_Index(log, j); if(status->node == node) { //When we find it, remove this node from the log. DynamicArray_RemoveAndReposition(log, j); //If there is no other nodes logged, delete the log. if(log->size == 0) { HashMap_Remove(tree->map, &occupant, sizeof(GObject*)); DynamicArray_Free(log); } //Stop looping break; } } } } } //Free the data contained within this tree DynamicArray_Free(node->data); //The parent node does the following, we must only free the root at the end. //Free this node //free(node); }
/// //Removes a game object from the oct tree and the tree's log // //Parameters: // tree: The tree to remove the object from // obj: the object to remove void OctTree_RemoveAndUnLog(OctTree* tree, GObject* obj) { //Remove from the treemap DynamicArray* objLog = (DynamicArray*)HashMap_Remove(tree->map, &obj, sizeof(GObject*)); //Delete the log DynamicArray_Free(objLog); //Remove the object from octtree OctTree_Remove(tree, obj); }
/// //Frees a hashmap //Does not free data!! Delete prior to this! OR have other references!!! // //Parameters: // map: The Hashmap to free void HashMap_Free(HashMap* map) { //for (unsigned int i = 0; i < map->size; i++) for(unsigned int i = 0; i < map->data->capacity; i++) { HashMap_KeyValuePair* pair = NULL; if((pair = *(HashMap_KeyValuePair**)DynamicArray_Index(map->data, i)) != NULL) { HashMap_KeyValuePair_Free(pair); DynamicArray_Remove(map->data, i); } } //free(map->data); DynamicArray_Free(map->data); free(map); }
/// //Loads and parses a .OBJ file constructing and returning //the Mesh it defines // //TODO: Put in code for parsing materials and groups // //Parameters: // fPath: The filepath of the .obj file to load // //Returns: // A pointer to a newly allocated Mesh following the specifications of the given .OBJ file Mesh* Loader_LoadOBJFile(const char* fPath) { //Open file in read mode FILE* fp = fopen(fPath, "r"); //MAke sure file is open if (fp == NULL) { printf("Error opening file %s.\n", fPath); return NULL; } //File opened correctly, begin parsing //Create struct to wrap 3 component attributes struct VertexAttr3 { GLfloat x, y, z; }; //Create struct to wrap 2 component attributes struct VertexAttr2 { GLfloat x, y; }; DynamicArray* vertices = DynamicArray_Allocate(); //Vertex coordinates DynamicArray* texCoords = DynamicArray_Allocate(); //Texture coordinates DynamicArray* normals = DynamicArray_Allocate(); //Normal Vectors DynamicArray* triangles = DynamicArray_Allocate(); //Complete Triangles DynamicArray_Initialize(vertices, sizeof(struct VertexAttr3)); DynamicArray_Initialize(texCoords, sizeof(struct VertexAttr2)); DynamicArray_Initialize(normals, sizeof(struct VertexAttr3)); DynamicArray_Initialize(triangles, sizeof(struct Triangle)); //Create a Cstring to hold each line of text char type[3]; //char line[100]; //Loop until we reach the end of the file while (!feof(fp)) { //Get first (max 3) letters indicating information we are parsing //if(fscanf_s(fp, "%s", type, 3) == EOF) break; //Break if we read past the end of the file (less than 3 characters were left) if(fscanf(fp, "%s", type) == EOF) break; //If we are reading Vertices, Texture Coordinates, or Normals if (type[0] == 'v') { //Normals if (type[1] == 'n') { struct VertexAttr3 vn; fscanf(fp, " %f %f %f", &vn.x, &vn.y, &vn.z); DynamicArray_Append(normals, &vn); } //Texture coordinates else if (type[1] == 't') { struct VertexAttr2 vt; fscanf(fp, " %f %f", &vt.x, &vt.y); DynamicArray_Append(texCoords, &vt); } //Vertices else { struct VertexAttr3 v; fscanf(fp, " %f %f %f", &v.x, &v.y, &v.z); DynamicArray_Append(vertices, &v); } } //Else if we are reading Face information else if (type[0] == 'f') { int indices[3]; struct Triangle t; struct Vertex v; struct VertexAttr3* vAtt3; struct VertexAttr2* vAtt2; //For each vertex in the triangle for (int i = 0; i < 3; i++) { //Get the face info & the amount of info given int infoCount = fscanf(fp, " %d/%d/%d", indices, indices + 1, indices + 2); switch (infoCount) { case 3: //Grabbing normals if present vAtt3 = (struct VertexAttr3*)DynamicArray_Index(normals, (indices[2] - 1)); v.nx = vAtt3->x; v.ny = vAtt3->y; v.nz = vAtt3->z; case 2: //Grabbing texture coords if present vAtt2 = (struct VertexAttr2*)DynamicArray_Index(texCoords, (indices[1] - 1)); v.tx = vAtt2->x; v.ty = vAtt2->y; case 1: //Grabbing vertex position vAtt3 = (struct VertexAttr3*)DynamicArray_Index(vertices, (indices[0] - 1)); v.x = vAtt3->x; v.y = vAtt3->y; v.z = vAtt3->z; } //Store vertex in triangle t *(&(t.a) + i) = v; } //And add to triangles array DynamicArray_Append(triangles, &t); } //Else if we are reading a comment else if (type[0] == '#') { //REad until you get to a new line char c = '0'; while (c != '\n' && c != '\r') { c = fgetc(fp); } } //Else if we don't know what we're reading else { //Read until the next line char c = '0'; while (c != '\n' && c != '\r') { c = fgetc(fp); } } }//End of file reached fclose(fp); //File parsed, creating mesh Mesh* parsed = Mesh_Allocate(); Mesh_Initialize(parsed, (struct Triangle*)triangles->data, triangles->size, GL_STATIC_DRAW); DynamicArray_Free(vertices); DynamicArray_Free(normals); DynamicArray_Free(texCoords); DynamicArray_Free(triangles); return parsed; }