From 26516c982959b1248e77712d19802260d0125e65 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Sat, 25 Sep 2021 03:47:40 -0700 Subject: [PATCH] more features --- src/Silkworm.c | 196 +++++++++++++++++++++++++++++++++++++-- src/Silkworm.h | 12 ++- visualc/Silkworm.vcxproj | 2 +- 3 files changed, 201 insertions(+), 9 deletions(-) diff --git a/src/Silkworm.c b/src/Silkworm.c index bac633f..71cfeb7 100644 --- a/src/Silkworm.c +++ b/src/Silkworm.c @@ -47,7 +47,7 @@ typedef struct Silkworm_Node float mass; float friction; float radius; - float pinned; + bool pinned; float pushFactor; bool destroyable; @@ -413,7 +413,10 @@ void Silkworm_Internal_DestroyCloth(Silkworm_Cloth* cloth) { free(cloth->nodeHash.buckets[i].elements[j].indexArray); } - free(cloth->nodeHash.buckets[i].elements); + if (cloth->nodeHash.buckets[i].elements != NULL) + { + free(cloth->nodeHash.buckets[i].elements); + } } for (i = 0; i < NUM_LINK_TRIANGLE_HASH_BUCKETS; i += 1) @@ -422,7 +425,10 @@ void Silkworm_Internal_DestroyCloth(Silkworm_Cloth* cloth) { free(cloth->linkHash.buckets[i].elements[j].indexArray); } - free(cloth->linkHash.buckets[i].elements); + if (cloth->linkHash.buckets[i].elements != NULL) + { + free(cloth->linkHash.buckets[i].elements); + } } for (i = 0; i < cloth->horizontalNodeCount; i += 1) @@ -434,7 +440,15 @@ void Silkworm_Internal_DestroyCloth(Silkworm_Cloth* cloth) free(cloth->nodeIndices[i]); } free(cloth->nodeIndices); - free(cloth); + + for (i = 0; i < cloth->triangleCount; i += 1) + { + if (cloth->triangles[i] != NULL) + { + free(cloth->triangles[i]); + } + } + free(cloth->triangles); if (context->clothIndexStackCount >= context->clothIndexStackCapacity) { @@ -444,6 +458,8 @@ void Silkworm_Internal_DestroyCloth(Silkworm_Cloth* cloth) context->clothIndexStack[context->clothIndexStackCount] = cloth->id; context->clothIndexStackCount += 1; + + free(cloth); } void Silkworm_DestroyCloth(double clothId) @@ -940,6 +956,47 @@ double Silkworm_CreateCloth(double xPosition, double yPosition, double width, do return (double)cloth->id; } +/* FIXME: this is very unsafe */ +double Silkworm_ClothHorizontalNodeCount(double clothId) +{ + return context->cloths[(uint32_t)clothId]->horizontalNodeCount; +} + +double Silkworm_ClothVerticalNodeCount(double clothId) +{ + return context->cloths[(uint32_t)clothId]->verticalNodeCount; +} + +void Silkworm_ClothFillNodeDataBuffer(double clothId) +{ + uint32_t i, j; + uint8_t* bufferAddress = context->currentBufferAddress; + Silkworm_Cloth* cloth = LookupCloth(clothId); + + uint8_t active = 0; + uint8_t pinned = 0; + + for (i = 0; i < cloth->horizontalNodeCount; i += 1) + { + for (j = 0; j < cloth->verticalNodeCount; j += 1) + { + active = context->nodes[cloth->nodeIndices[i][j]] != NULL; + + memcpy(bufferAddress, &active, sizeof(uint8_t)); + bufferAddress += sizeof(uint8_t); + + pinned = 0; + if (context->nodes[cloth->nodeIndices[i][j]] != NULL) + { + pinned = context->nodes[cloth->nodeIndices[i][j]]->pinned; + } + + memcpy(bufferAddress, &pinned, sizeof(uint8_t)); + bufferAddress += sizeof(uint8_t); + } + } +} + void Silkworm_ApplyWind(double xSpeed, double ySpeed) { uint32_t i, j, k; @@ -969,7 +1026,7 @@ void Silkworm_ApplyWind(double xSpeed, double ySpeed) } } -void Silkworm_SetTriangleBuffer(const char* bufferId) +void Silkworm_SetBuffer(const char* bufferId) { context->currentBufferAddress = (uint8_t*)bufferId; } @@ -1218,6 +1275,19 @@ double Silkworm_FillEditorBuffer() if (node != NULL) { + if (node->pinned) + { + color.r = 255; + color.g = 255; + color.b = 0; + } + else + { + color.r = 255; + color.g = 0; + color.b = 0; + } + /* top left triangle */ position.x = node->position.x - node->radius; position.y = node->position.y - node->radius; @@ -1293,7 +1363,7 @@ void Silkworm_PushNodesInRadius(double x, double y, double radius, double xDirec { Silkworm_Node* node = context->nodes[i]; - if (node != NULL) + if (node != NULL && !node->pinned) { float xDistance = (float)fabs((float)x - node->position.x); float yDistance = (float)fabs((float)y - node->position.y); @@ -1309,6 +1379,56 @@ void Silkworm_PushNodesInRadius(double x, double y, double radius, double xDirec } } +void Silkworm_PinNodesInRadius(double x, double y, double radius) +{ + /* TODO: spatial hash implementation */ + + uint32_t i; + + for (i = 0; i < context->nodeCount; i += 1) + { + Silkworm_Node* node = context->nodes[i]; + + if (node != NULL) + { + float xDistance = (float)fabs((float)x - node->position.x); + float yDistance = (float)fabs((float)y - node->position.y); + + float squareDistance = xDistance * xDistance + yDistance * yDistance; + + if (squareDistance <= radius * radius) + { + node->pinned = true; + } + } + } +} + +void Silkworm_UnpinNodesInRadius(double x, double y, double radius) +{ + /* TODO: spatial hash implementation */ + + uint32_t i; + + for (i = 0; i < context->nodeCount; i += 1) + { + Silkworm_Node* node = context->nodes[i]; + + if (node != NULL) + { + float xDistance = (float)fabs((float)x - node->position.x); + float yDistance = (float)fabs((float)y - node->position.y); + + float squareDistance = xDistance * xDistance + yDistance * yDistance; + + if (squareDistance <= radius * radius) + { + node->pinned = false; + } + } + } +} + void Silkworm_DestroyNodesInRadius(double x, double y, double radius) { /* TODO: spatial hash implementation */ @@ -1332,6 +1452,54 @@ void Silkworm_DestroyNodesInRadius(double x, double y, double radius) } } } + + Silkworm_PerformDestroys(); +} + +double Silkworm_DestroyClothInRadius(double x, double y, double radius) +{ + /* TODO: spatial hash implementation */ + + uint32_t i, j; + double clothId = -1; + + for (i = 0; i < context->nodeCount; i += 1) + { + Silkworm_Node* node = context->nodes[i]; + + if (node != NULL) + { + float xDistance = (float)fabs((float)x - node->position.x); + float yDistance = (float)fabs((float)y - node->position.y); + + float squareDistance = xDistance * xDistance + yDistance * yDistance; + + if (squareDistance <= radius * radius) + { + for (j = 0; j < context->clothCount; j += 1) + { + Silkworm_Cloth* cloth = context->cloths[j]; + + if (cloth != NULL) + { + /* if the node has a triangle in the cloth, it's part of the cloth! */ + uint32_t arrayCount = 0; + NodeTriangleHashTable_Fetch(&cloth->nodeHash, node, &arrayCount); + + if (arrayCount > 0) + { + clothId = (double)cloth->id; + Silkworm_Internal_DestroyCloth(cloth); + break; + } + } + } + } + } + } + + Silkworm_PerformDestroys(); + return clothId; } void Silkworm_ClearAll() @@ -1348,3 +1516,19 @@ void Silkworm_ClearAll() Silkworm_PerformDestroys(); } + +void Silkworm_Finish() +{ + Silkworm_ClearAll(); + + free(context->nodes); + free(context->links); + free(context->cloths); + + free(context->nodeIndexStack); + free(context->linkIndexStack); + free(context->clothIndexStack); + + free(context); + context = NULL; +} \ No newline at end of file diff --git a/src/Silkworm.h b/src/Silkworm.h index bf65f90..067a5f3 100644 --- a/src/Silkworm.h +++ b/src/Silkworm.h @@ -60,19 +60,23 @@ SILKWORMAPI void Silkworm_Init(); SILKWORMAPI void Silkworm_Update(double delta); SILKWORMAPI void Silkworm_ApplyWind(double xSpeed, double ySpeed); +SILKWORMAPI void Silkworm_SetBuffer(const char* bufferId); + SILKWORMAPI double Silkworm_CreateNode(double xPosition, double yPosition, double mass, double friction, double radius, double pushFactor); SILKWORMAPI void Silkworm_NodeSetDestroyable(double nodeId); SILKWORMAPI double Silkworm_CreateLink(double aId, double bId, double distance, double tearThreshold); -SILKWORMAPI double Silkworm_CreateCloth(double xPosition, double yPosition, double horizontalNodeCount, double verticalNodeCount, double mass, double friction, double windFactor, double tearThreshold); +SILKWORMAPI double Silkworm_CreateCloth(double xPosition, double yPosition, double width, double height, double mass, double friction, double windFactor, double tearThreshold); +SILKWORMAPI double Silkworm_ClothHorizontalNodeCount(double clothId); +SILKWORMAPI double Silkworm_ClothVerticalNodeCount(double clothId); SILKWORMAPI void Silkworm_ClothNodePin(double clothId, double i, double j); SILKWORMAPI void Silkworm_ClothNodeUnpin(double clothId, double i, double j); SILKWORMAPI void Silkworm_ClothNodeDestroy(double clothId, double i, double j); +SILKWORMAPI void Silkworm_ClothFillNodeDataBuffer(double clothId); SILKWORMAPI void Silkworm_DestroyCloth(double clothId); -SILKWORMAPI void Silkworm_SetTriangleBuffer(const char* bufferId); SILKWORMAPI double Silkworm_ClothFillTriangleBuffer(double clothId, double leftUV, double widthUV, double topUV, double heightUV); SILKWORMAPI double Silkworm_GetEditorBufferRequiredSize(); @@ -80,9 +84,13 @@ SILKWORMAPI double Silkworm_FillEditorBuffer(); SILKWORMAPI void Silkworm_DestroyNode(double nodeId); +SILKWORMAPI void Silkworm_PinNodesInRadius(double x, double y, double radius); +SILKWORMAPI void Silkworm_UnpinNodesInRadius(double x, double y, double radius); SILKWORMAPI void Silkworm_PushNodesInRadius(double x, double y, double radius, double xDirection, double yDirection); SILKWORMAPI void Silkworm_DestroyNodesInRadius(double x, double y, double radius); +SILKWORMAPI double Silkworm_DestroyClothInRadius(double x, double y, double radius); SILKWORMAPI void Silkworm_ClearAll(); +SILKWORMAPI void Silkworm_Finish(); #endif /* SILKWORM_H */ diff --git a/visualc/Silkworm.vcxproj b/visualc/Silkworm.vcxproj index 94b617c..ba0de5c 100644 --- a/visualc/Silkworm.vcxproj +++ b/visualc/Silkworm.vcxproj @@ -19,7 +19,7 @@ - {6DB15344-E000-45CB-A48A-1D72F7D6E945} + {4F20502A-F926-4D12-872D-64AC2E065078} Silkworm 10.0