From da4062c30e5dc26929e2f82e0be955f44810c111 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Thu, 30 Sep 2021 22:50:32 -0700 Subject: [PATCH] change rope and cloth to use pointers to nodes instead of indices --- src/Silkworm.c | 216 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 143 insertions(+), 73 deletions(-) diff --git a/src/Silkworm.c b/src/Silkworm.c index 9196464..52d2fac 100644 --- a/src/Silkworm.c +++ b/src/Silkworm.c @@ -58,6 +58,25 @@ static inline Silkworm_Vector2 Vector2_Normalize(Silkworm_Vector2 vector) typedef struct Silkworm_Link Silkworm_Link; +typedef struct Silkworm_NodeClothReference +{ + uint32_t clothId; + uint32_t horizontalIndex; + uint32_t verticalIndex; +} Silkworm_NodeClothReference; + +typedef struct Silkworm_NodeRopeReference +{ + uint32_t ropeId; + uint32_t index; +} Silkworm_NodeRopeReference; + +typedef enum Silkworm_NodeParentType +{ + ClothParent, + RopeParent +} Silkworm_NodeParentType; + typedef struct Silkworm_Node { uint64_t id; @@ -77,6 +96,14 @@ typedef struct Silkworm_Node Silkworm_Link** links; uint32_t linkCount; + + Silkworm_NodeParentType nodeParentType; + + union + { + Silkworm_NodeClothReference clothReference; + Silkworm_NodeRopeReference ropeReference; + } parent; } Silkworm_Node; struct Silkworm_Link @@ -285,7 +312,8 @@ typedef struct Silkworm_Cloth uint32_t horizontalNodeCount; uint32_t verticalNodeCount; - uint64_t** nodeIndices; /* x by y grid of indices */ + /* note that the cloth doesn't own the nodes, just has pointers to them */ + Silkworm_Node*** nodes; /* x by y grid of indices */ Silkworm_Triangle** triangles; /* array of pointers so we can use NULL */ uint32_t triangleCount; @@ -298,7 +326,8 @@ typedef struct Silkworm_Rope { uint64_t id; - uint64_t* nodeIndices; + /* note that the rope doesn't own the nodes, just has pointers to them */ + Silkworm_Node** nodes; uint32_t nodeCount; float windFactor; @@ -431,6 +460,11 @@ static inline Silkworm_Cloth* LookupCloth(uint64_t clothId) return context->cloths[clothId]; } +static inline Silkworm_Rope* LookupRope(double ropeId) +{ + return context->ropes[(uint32_t)ropeId]; +} + /* we defer actual destruction to Update to avoid issues with NULL */ void Silkworm_DestroyNode(double nodeId) @@ -510,11 +544,16 @@ void Silkworm_Internal_DestroyCloth(Silkworm_Cloth* cloth) { for (j = 0; j < cloth->verticalNodeCount; j += 1) { - Silkworm_DestroyNode((double)cloth->nodeIndices[i][j]); + Silkworm_Node* node = cloth->nodes[i][j]; + + if (node != NULL) + { + Silkworm_DestroyNode((double)node->id); + } } - free(cloth->nodeIndices[i]); + free(cloth->nodes[i]); } - free(cloth->nodeIndices); + free(cloth->nodes); for (i = 0; i < cloth->triangleCount; i += 1) { @@ -609,12 +648,12 @@ void Silkworm_PerformDestroys() for (i = 0; i < context->nodeCount; i += 1) { Silkworm_Node* node = context->nodes[i]; + if (node != NULL && node->markedForDestroy) { - /* find cloth to remove from relevant triangles */ - for (j = 0; j < context->clothCount; j += 1) + if (node->nodeParentType == ClothParent) { - Silkworm_Cloth* cloth = context->cloths[j]; + Silkworm_Cloth* cloth = LookupCloth(node->parent.clothReference.clothId); if (cloth != NULL) { @@ -631,6 +670,17 @@ void Silkworm_PerformDestroys() cloth->triangles[triangleIndex] = NULL; } } + + cloth->nodes[node->parent.clothReference.horizontalIndex][node->parent.clothReference.verticalIndex] = NULL; + } + } + else if (node->nodeParentType == RopeParent) + { + Silkworm_Rope* rope = LookupRope((double)node->parent.ropeReference.ropeId); + + if (rope != NULL) + { + rope->nodes[node->parent.ropeReference.index] = NULL; } } @@ -801,21 +851,31 @@ void Silkworm_NodeSetDestroyable(double nodeId) void Silkworm_ClothNodePin(double clothId, double i, double j) { Silkworm_Cloth* cloth = LookupCloth(clothId); - context->nodes[cloth->nodeIndices[(uint64_t)i][(uint64_t)j]]->pinned = true; + Silkworm_Node* node = cloth->nodes[(uint64_t)i][(uint64_t)j]; + if (node != NULL) + { + node->pinned = true; + } } void Silkworm_ClothNodeUnpin(double clothId, double i, double j) { Silkworm_Cloth* cloth = LookupCloth(clothId); - context->nodes[cloth->nodeIndices[(uint64_t)i][(uint64_t)j]]->pinned = false; + Silkworm_Node* node = cloth->nodes[(uint64_t)i][(uint64_t)j]; + if (node != NULL) + { + node->pinned = false; + } } void Silkworm_ClothNodeDestroy(double clothId, double i, double j) { Silkworm_Cloth* cloth = LookupCloth(clothId); - uint64_t nodeIndex = cloth->nodeIndices[(uint64_t)i][(uint64_t)j]; - Silkworm_Node* node = context->nodes[nodeIndex]; - Silkworm_DestroyNode(nodeIndex); + Silkworm_Node* node = cloth->nodes[(uint64_t)i][(uint64_t)j]; + if (node != NULL) + { + Silkworm_DestroyNode(node->id); + } } double Silkworm_CreateLink(double aId, double bId, double distance, double tearThreshold) @@ -868,7 +928,7 @@ double Silkworm_CreateCloth(double xPosition, double yPosition, double width, do cloth->horizontalNodeCount = ((uint32_t)width / context->clothDensity) + 1; cloth->verticalNodeCount = ((uint32_t)height / context->clothDensity) + 1; - cloth->nodeIndices = malloc(sizeof(uint64_t*) * cloth->horizontalNodeCount); + cloth->nodes = malloc(sizeof(Silkworm_Node**) * cloth->horizontalNodeCount); uint64_t id; @@ -904,20 +964,27 @@ double Silkworm_CreateCloth(double xPosition, double yPosition, double width, do for (i = 0; i < cloth->horizontalNodeCount; i += 1) { - cloth->nodeIndices[i] = malloc(sizeof(uint64_t) * cloth->verticalNodeCount); + cloth->nodes[i] = malloc(sizeof(Silkworm_Node*) * cloth->verticalNodeCount); for (j = 0; j < cloth->verticalNodeCount; j += 1) { uint64_t nodeId = (uint64_t) Silkworm_CreateNode(xPosition + i * context->clothDensity, yPosition + j * context->clothDensity, mass, friction, 1, 1.0, windFactor); - cloth->nodeIndices[i][j] = nodeId; + Silkworm_Node *node = LookupNode(nodeId); + + cloth->nodes[i][j] = node; if (j == 0) { - Silkworm_ClothNodePin((double)cloth->id, (double)i, (double)j); + node->pinned = true; } - Silkworm_NodeSetDestroyable((double)nodeId); + node->destroyable = true; + + node->nodeParentType = ClothParent; + node->parent.clothReference.clothId = cloth->id; + node->parent.clothReference.horizontalIndex = i; + node->parent.clothReference.verticalIndex = j; } } @@ -932,9 +999,9 @@ double Silkworm_CreateCloth(double xPosition, double yPosition, double width, do { cloth->triangles[triangleIndex] = malloc(sizeof(Silkworm_Triangle)); - cloth->triangles[triangleIndex]->a = context->nodes[cloth->nodeIndices[i][j]]; - cloth->triangles[triangleIndex]->b = context->nodes[cloth->nodeIndices[i + 1][j]]; - cloth->triangles[triangleIndex]->c = context->nodes[cloth->nodeIndices[i][j + 1]]; + cloth->triangles[triangleIndex]->a = cloth->nodes[i][j]; + cloth->triangles[triangleIndex]->b = cloth->nodes[i + 1][j]; + cloth->triangles[triangleIndex]->c = cloth->nodes[i][j + 1]; cloth->triangles[triangleIndex]->orientation = UpperLeft; cloth->triangles[triangleIndex]->aHorizontalIndex = i; @@ -946,9 +1013,9 @@ double Silkworm_CreateCloth(double xPosition, double yPosition, double width, do cloth->triangles[triangleIndex]->cHorizontalIndex = i; cloth->triangles[triangleIndex]->cVerticalIndex = j + 1; - NodeTriangleHashTable_Insert(&cloth->nodeHash, context->nodes[cloth->nodeIndices[i][j]], triangleIndex); - NodeTriangleHashTable_Insert(&cloth->nodeHash, context->nodes[cloth->nodeIndices[i + 1][j]], triangleIndex); - NodeTriangleHashTable_Insert(&cloth->nodeHash, context->nodes[cloth->nodeIndices[i][j + 1]], triangleIndex); + NodeTriangleHashTable_Insert(&cloth->nodeHash, cloth->nodes[i][j], triangleIndex); + NodeTriangleHashTable_Insert(&cloth->nodeHash, cloth->nodes[i + 1][j], triangleIndex); + NodeTriangleHashTable_Insert(&cloth->nodeHash, cloth->nodes[i][j + 1], triangleIndex); triangleIndex += 1; } @@ -957,9 +1024,9 @@ double Silkworm_CreateCloth(double xPosition, double yPosition, double width, do { cloth->triangles[triangleIndex] = malloc(sizeof(Silkworm_Triangle)); - cloth->triangles[triangleIndex]->a = context->nodes[cloth->nodeIndices[i][j]]; - cloth->triangles[triangleIndex]->b = context->nodes[cloth->nodeIndices[i - 1][j]]; - cloth->triangles[triangleIndex]->c = context->nodes[cloth->nodeIndices[i][j - 1]]; + cloth->triangles[triangleIndex]->a = cloth->nodes[i][j]; + cloth->triangles[triangleIndex]->b = cloth->nodes[i - 1][j]; + cloth->triangles[triangleIndex]->c = cloth->nodes[i][j - 1]; cloth->triangles[triangleIndex]->orientation = BottomRight; cloth->triangles[triangleIndex]->aHorizontalIndex = i; @@ -971,9 +1038,9 @@ double Silkworm_CreateCloth(double xPosition, double yPosition, double width, do cloth->triangles[triangleIndex]->cHorizontalIndex = i; cloth->triangles[triangleIndex]->cVerticalIndex = j - 1; - NodeTriangleHashTable_Insert(&cloth->nodeHash, context->nodes[cloth->nodeIndices[i][j]], triangleIndex); - NodeTriangleHashTable_Insert(&cloth->nodeHash, context->nodes[cloth->nodeIndices[i - 1][j]], triangleIndex); - NodeTriangleHashTable_Insert(&cloth->nodeHash, context->nodes[cloth->nodeIndices[i][j - 1]], triangleIndex); + NodeTriangleHashTable_Insert(&cloth->nodeHash, cloth->nodes[i][j], triangleIndex); + NodeTriangleHashTable_Insert(&cloth->nodeHash, cloth->nodes[i - 1][j], triangleIndex); + NodeTriangleHashTable_Insert(&cloth->nodeHash, cloth->nodes[i][j - 1], triangleIndex); triangleIndex += 1; } @@ -988,13 +1055,13 @@ double Silkworm_CreateCloth(double xPosition, double yPosition, double width, do { if (i - 1 >= 0) { - double linkId = Silkworm_CreateLink((double)cloth->nodeIndices[i - 1][j], (double)cloth->nodeIndices[i][j], context->clothDensity, tearThreshold); + double linkId = Silkworm_CreateLink((double)cloth->nodes[i - 1][j]->id, (double)cloth->nodes[i][j]->id, context->clothDensity, tearThreshold); uint32_t indexArrayOneCount = 0; - uint32_t* indexArrayOne = NodeTriangleHashTable_Fetch(&cloth->nodeHash, context->nodes[cloth->nodeIndices[i - 1][j]], &indexArrayOneCount); + uint32_t* indexArrayOne = NodeTriangleHashTable_Fetch(&cloth->nodeHash, cloth->nodes[i - 1][j], &indexArrayOneCount); uint32_t indexArrayTwoCount = 0; - uint32_t* indexArrayTwo = NodeTriangleHashTable_Fetch(&cloth->nodeHash, context->nodes[cloth->nodeIndices[i][j]], &indexArrayTwoCount); + uint32_t* indexArrayTwo = NodeTriangleHashTable_Fetch(&cloth->nodeHash, cloth->nodes[i][j], &indexArrayTwoCount); for (k = 0; k < indexArrayOneCount; k += 1) { @@ -1011,13 +1078,13 @@ double Silkworm_CreateCloth(double xPosition, double yPosition, double width, do if (j - 1 >= 0) { - double linkId = Silkworm_CreateLink((double)cloth->nodeIndices[i][j - 1], (double)cloth->nodeIndices[i][j], context->clothDensity, tearThreshold); + double linkId = Silkworm_CreateLink((double)cloth->nodes[i][j - 1]->id, (double)cloth->nodes[i][j]->id, context->clothDensity, tearThreshold); uint32_t indexArrayOneCount = 0; - uint32_t* indexArrayOne = NodeTriangleHashTable_Fetch(&cloth->nodeHash, context->nodes[cloth->nodeIndices[i][j - 1]], &indexArrayOneCount); + uint32_t* indexArrayOne = NodeTriangleHashTable_Fetch(&cloth->nodeHash, cloth->nodes[i][j - 1], &indexArrayOneCount); uint32_t indexArrayTwoCount = 0; - uint32_t* indexArrayTwo = NodeTriangleHashTable_Fetch(&cloth->nodeHash, context->nodes[cloth->nodeIndices[i][j]], &indexArrayTwoCount); + uint32_t* indexArrayTwo = NodeTriangleHashTable_Fetch(&cloth->nodeHash, cloth->nodes[i][j], &indexArrayTwoCount); for (k = 0; k < indexArrayOneCount; k += 1) { @@ -1061,15 +1128,15 @@ void Silkworm_ClothFillNodeDataBuffer(double clothId) { for (j = 0; j < cloth->verticalNodeCount; j += 1) { - active = context->nodes[cloth->nodeIndices[i][j]] != NULL; + active = cloth->nodes[i][j] != NULL; memcpy(bufferAddress, &active, sizeof(uint8_t)); bufferAddress += sizeof(uint8_t); pinned = 0; - if (context->nodes[cloth->nodeIndices[i][j]] != NULL) + if (cloth->nodes[i][j] != NULL) { - pinned = context->nodes[cloth->nodeIndices[i][j]]->pinned; + pinned = cloth->nodes[i][j]->pinned; } memcpy(bufferAddress, &pinned, sizeof(uint8_t)); @@ -1216,27 +1283,26 @@ double Silkworm_ClothFillTriangleBuffer(double clothId, double leftUV, double wi return (double)triangleCount * 3; } -Silkworm_Rope* LookupRope(double ropeId) -{ - return context->ropes[(uint32_t)ropeId]; -} - double Silkworm_RopeAddNode(double ropeId, double xPosition, double yPosition, double length) { Silkworm_Rope *rope = LookupRope(ropeId); if (rope != NULL) { - double nodeId = Silkworm_CreateNode(xPosition, yPosition, rope->nodeMass, rope->friction, 1.0, rope->pushFactor, rope->windFactor); + uint64_t nodeId = (uint64_t) Silkworm_CreateNode(xPosition, yPosition, rope->nodeMass, rope->friction, 1.0, rope->pushFactor, rope->windFactor); - rope->nodeIndices = realloc(rope->nodeIndices, sizeof(uint64_t) * (rope->nodeCount + 1)); - rope->nodeIndices[rope->nodeCount] = nodeId; + Silkworm_Node* node = LookupNode(nodeId); + + rope->nodes = realloc(rope->nodes, sizeof(Silkworm_Node*) * (rope->nodeCount + 1)); + rope->nodes[rope->nodeCount] = node; rope->nodeCount += 1; - Silkworm_Node* node = LookupNode((uint64_t)nodeId); node->destroyable = false; + node->nodeParentType = RopeParent; + node->parent.ropeReference.ropeId = rope->id; + node->parent.ropeReference.index = rope->nodeCount - 1; - Silkworm_CreateLink((double)rope->nodeIndices[rope->nodeCount - 2], (double)rope->nodeIndices[rope->nodeCount - 1], length, rope->tearThreshold); + Silkworm_CreateLink((double)rope->nodes[rope->nodeCount - 2]->id, (double)rope->nodes[rope->nodeCount - 1]->id, length, rope->tearThreshold); return nodeId; } @@ -1252,8 +1318,8 @@ double Silkworm_RopeVerticalLength(double ropeId) if (rope != NULL) { - Silkworm_Node* startNode = LookupNode(rope->nodeIndices[0]); - Silkworm_Node* endNode = LookupNode(rope->nodeIndices[rope->nodeCount - 1]); + Silkworm_Node* startNode = rope->nodes[0]; + Silkworm_Node* endNode = rope->nodes[rope->nodeCount - 1]; if (startNode != NULL && endNode != NULL) { @@ -1279,7 +1345,7 @@ double Silkworm_RopeNearestX(double ropeId, double xPosition, double yPosition) { for (i = 0; i < rope->nodeCount; i += 1) { - Silkworm_Node* node = LookupNode(rope->nodeIndices[i]); + Silkworm_Node* node = rope->nodes[i]; if (node != NULL) { @@ -1314,7 +1380,7 @@ double Silkworm_RopeNearestY(double ropeId, double xPosition, double yPosition) { for (i = 0; i < rope->nodeCount; i += 1) { - Silkworm_Node* node = LookupNode(rope->nodeIndices[i]); + Silkworm_Node* node = rope->nodes[i]; if (node != NULL) { @@ -1339,7 +1405,7 @@ void Silkworm_UnpinRope(double ropeId) { Silkworm_Rope* rope = LookupRope(ropeId); - Silkworm_Node* node = LookupNode(rope->nodeIndices[0]); + Silkworm_Node* node = rope->nodes[0]; if (node != NULL) { @@ -1377,16 +1443,21 @@ double Silkworm_RopeCreate(double xPosition, double yPosition, double mass, doub rope->tearThreshold = tearThreshold; rope->pushFactor = pushFactor; - // TODO: create first node here - rope->nodeIndices = malloc(sizeof(uint64_t)); + uint64_t nodeId = (uint64_t) Silkworm_CreateNode(xPosition, yPosition, rope->nodeMass, rope->friction, 1.0, rope->pushFactor, rope->windFactor); + + Silkworm_Node* node = LookupNode(nodeId); + + rope->nodes = malloc(sizeof(Silkworm_Node*)); rope->nodeCount = 1; + rope->nodes[0] = node; - rope->nodeIndices[0] = Silkworm_CreateNode(xPosition, yPosition, rope->nodeMass, rope->friction, 1.0, rope->pushFactor, rope->windFactor); - - Silkworm_Node* node = LookupNode(rope->nodeIndices[0]); node->pinned = true; node->destroyable = false; + node->nodeParentType = RopeParent; + node->parent.ropeReference.ropeId = rope->id; + node->parent.ropeReference.index = 0; + return (double)rope->id; } @@ -1408,10 +1479,13 @@ void Silkworm_RopeDestroy(double ropeId) for (i = 0; i < rope->nodeCount; i += 1) { - Silkworm_DestroyNode((double)rope->nodeIndices[i]); + if (rope->nodes[i] != NULL) + { + Silkworm_DestroyNode((double)rope->nodes[i]->id); + } } - free(rope->nodeIndices); + free(rope->nodes); context->ropes[rope->id] = NULL; free(rope); @@ -1440,8 +1514,10 @@ double Silkworm_RopeFillBuffer(double ropeId, double width, double leftUV, doubl for (i = 0; i < rope->nodeCount - 1; i += 1) { - Silkworm_Node* nodeOne = LookupNode(rope->nodeIndices[i]); - Silkworm_Node* nodeTwo = LookupNode(rope->nodeIndices[i + 1]); + Silkworm_Node* nodeOne = rope->nodes[i]; + Silkworm_Node* nodeTwo = rope->nodes[i + 1]; + + if (nodeOne == NULL || nodeTwo == NULL) { continue; } Silkworm_Vector2 forwardDirection; forwardDirection.x = nodeTwo->position.x - nodeOne->position.x; @@ -1894,20 +1970,14 @@ double Silkworm_DestroyClothInRadius(double x, double y, double radius) if (squareDistance <= radius * radius) { - for (j = 0; j < context->clothCount; j += 1) + if (node->nodeParentType == ClothParent) { - Silkworm_Cloth* cloth = context->cloths[j]; + Silkworm_Cloth* cloth = LookupCloth(node->parent.clothReference.clothId); 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 = cloth->id; - } + clothId = cloth->id; + break; } } }