From 8d298e84a03166a24c5bd0e25f55535285ce3dde Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Thu, 30 Sep 2021 15:47:56 -0700 Subject: [PATCH] various rope fixes --- src/Silkworm.c | 113 +++++++++++++++++++++++++++---------------------- src/Silkworm.h | 7 +-- 2 files changed, 67 insertions(+), 53 deletions(-) diff --git a/src/Silkworm.c b/src/Silkworm.c index 107ecd3..7d86b69 100644 --- a/src/Silkworm.c +++ b/src/Silkworm.c @@ -70,6 +70,7 @@ typedef struct Silkworm_Node float radius; bool pinned; float pushFactor; + float windFactor; bool destroyable; bool markedForDestroy; /* mutual recursion on nodes/links so this makes it easier to track destroys */ @@ -280,7 +281,6 @@ static inline void LinkTriangleHashTable_Insert( typedef struct Silkworm_Cloth { uint64_t id; - float windFactor; uint32_t horizontalNodeCount; uint32_t verticalNodeCount; @@ -733,7 +733,7 @@ void Silkworm_Update(double deltaTime) Silkworm_PerformDestroys(); } -double Silkworm_CreateNode(double xPosition, double yPosition, double mass, double friction, double radius, double pushFactor) +double Silkworm_CreateNode(double xPosition, double yPosition, double mass, double friction, double radius, double pushFactor, double windFactor) { Silkworm_Node* node = malloc(sizeof(Silkworm_Node)); uint64_t id; @@ -766,6 +766,7 @@ double Silkworm_CreateNode(double xPosition, double yPosition, double mass, doub node->friction = (float)friction; node->radius = (float)radius; node->pushFactor = (float)pushFactor; + node->windFactor = (float)windFactor; node->pinned = false; node->destroyable = false; node->markedForDestroy = false; @@ -860,7 +861,6 @@ double Silkworm_CreateCloth(double xPosition, double yPosition, double width, do Silkworm_Cloth* cloth = malloc(sizeof(Silkworm_Cloth)); - cloth->windFactor = (float)windFactor; cloth->horizontalNodeCount = ((uint32_t)width / context->clothDensity) + 1; cloth->verticalNodeCount = ((uint32_t)height / context->clothDensity) + 1; cloth->nodeIndices = malloc(sizeof(uint64_t*) * cloth->horizontalNodeCount); @@ -903,7 +903,7 @@ double Silkworm_CreateCloth(double xPosition, double yPosition, double width, do 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); + 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; @@ -1075,29 +1075,17 @@ void Silkworm_ClothFillNodeDataBuffer(double clothId) void Silkworm_ApplyWind(double xSpeed, double ySpeed) { - uint32_t i, j, k; - Silkworm_Cloth* cloth; + uint32_t i; Silkworm_Node* node; - for (i = 0; i < context->clothCount; i += 1) + for (i = 0; i < context->nodeCount; i += 1) { - if (context->cloths[i] != NULL) + node = LookupNode(i); + + if (node != NULL && !node->pinned) { - cloth = context->cloths[i]; - - for (j = 0; j < cloth->horizontalNodeCount; j += 1) - { - for (k = 0; k < cloth->verticalNodeCount; k += 1) - { - node = context->nodes[cloth->nodeIndices[j][k]]; - - if (node != NULL && !node->pinned) - { - node->position.x += (float)xSpeed * 0.025f * cloth->windFactor; - node->position.y += (float)ySpeed * 0.025f * cloth->windFactor; - } - } - } + node->position.x += (float)xSpeed * 0.025f * node->windFactor; + node->position.y += (float)ySpeed * 0.025f * node->windFactor; } } } @@ -1234,7 +1222,7 @@ double Silkworm_RopeAddNode(double ropeId, double xPosition, double yPosition, d if (rope != NULL) { - double nodeId = Silkworm_CreateNode(xPosition, yPosition, rope->nodeMass, rope->friction, 1.0, rope->pushFactor); + double nodeId = 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; @@ -1259,16 +1247,20 @@ double Silkworm_RopeVerticalLength(double ropeId) if (rope != NULL) { - /* return the distance between the end node Y and the start Y */ - return LookupNode(rope->nodeIndices[rope->nodeCount - 1])->position.y - LookupNode(rope->nodeIndices[0])->position.y; - } - else - { - return -1; + Silkworm_Node* startNode = LookupNode(rope->nodeIndices[0]); + Silkworm_Node* endNode = LookupNode(rope->nodeIndices[rope->nodeCount - 1]); + + if (startNode != NULL && endNode != NULL) + { + /* return the distance between the end node Y and the start Y */ + return fabs(endNode->position.y - startNode->position.y); + } } + + return -1; } -double Silkworm_NearestX(double ropeId, double xPosition, double yPosition) +double Silkworm_RopeNearestX(double ropeId, double xPosition, double yPosition) { uint32_t i; float nearestSqrDistance, nearestX; @@ -1284,15 +1276,18 @@ double Silkworm_NearestX(double ropeId, double xPosition, double yPosition) { Silkworm_Node* node = LookupNode(rope->nodeIndices[i]); - float yDistance = node->position.y - yPosition; - float xDistance = node->position.x - xPosition; - - float sqrDistance = xDistance * xDistance + yDistance * yDistance; - - if (sqrDistance < nearestSqrDistance) + if (node != NULL) { - nearestSqrDistance = sqrDistance; - nearestX = node->position.x; + float yDistance = node->position.y - yPosition; + float xDistance = node->position.x - xPosition; + + float sqrDistance = xDistance * xDistance + yDistance * yDistance; + + if (sqrDistance < nearestSqrDistance) + { + nearestSqrDistance = sqrDistance; + nearestX = node->position.x; + } } } } @@ -1300,7 +1295,7 @@ double Silkworm_NearestX(double ropeId, double xPosition, double yPosition) return nearestX; } -double Silkworm_NearestY(double ropeId, double xPosition, double yPosition) +double Silkworm_RopeNearestY(double ropeId, double xPosition, double yPosition) { uint32_t i; float nearestSqrDistance, nearestY; @@ -1316,15 +1311,18 @@ double Silkworm_NearestY(double ropeId, double xPosition, double yPosition) { Silkworm_Node* node = LookupNode(rope->nodeIndices[i]); - float yDistance = node->position.y - yPosition; - float xDistance = node->position.x - xPosition; - - float sqrDistance = xDistance * xDistance + yDistance * yDistance; - - if (sqrDistance < nearestSqrDistance) + if (node != NULL) { - nearestSqrDistance = sqrDistance; - nearestY = node->position.y; + float yDistance = node->position.y - yPosition; + float xDistance = node->position.x - xPosition; + + float sqrDistance = xDistance * xDistance + yDistance * yDistance; + + if (sqrDistance < nearestSqrDistance) + { + nearestSqrDistance = sqrDistance; + nearestY = node->position.y; + } } } } @@ -1332,6 +1330,18 @@ double Silkworm_NearestY(double ropeId, double xPosition, double yPosition) return nearestY; } +void Silkworm_UnpinRope(double ropeId) +{ + Silkworm_Rope* rope = LookupRope(ropeId); + + Silkworm_Node* node = LookupNode(rope->nodeIndices[0]); + + if (node != NULL) + { + node->pinned = false; + } +} + double Silkworm_RopeCreate(double xPosition, double yPosition, double mass, double friction, double windFactor, double pushFactor, double tearThreshold) { Silkworm_Rope* rope = malloc(sizeof(Silkworm_Rope)); @@ -1366,7 +1376,7 @@ double Silkworm_RopeCreate(double xPosition, double yPosition, double mass, doub rope->nodeIndices = malloc(sizeof(uint64_t)); rope->nodeCount = 1; - rope->nodeIndices[0] = Silkworm_CreateNode(xPosition, yPosition, rope->nodeMass, rope->friction, 1.0, rope->pushFactor); + 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; @@ -1397,6 +1407,9 @@ void Silkworm_RopeDestroy(double ropeId) } free(rope->nodeIndices); + + context->ropes[rope->id] = NULL; + free(rope); } } @@ -1829,7 +1842,7 @@ void Silkworm_DestroyNodesInRadius(double x, double y, double radius) { Silkworm_Node* node = context->nodes[i]; - if (node != NULL) + if (node != NULL && node->destroyable) { float xDistance = (float)fabs((float)x - node->position.x); float yDistance = (float)fabs((float)y - node->position.y); diff --git a/src/Silkworm.h b/src/Silkworm.h index 0cb1c86..11b03e1 100644 --- a/src/Silkworm.h +++ b/src/Silkworm.h @@ -62,7 +62,7 @@ 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 double Silkworm_CreateNode(double xPosition, double yPosition, double mass, double friction, double radius, double pushFactor, double windFactor); SILKWORMAPI void Silkworm_NodeSetDestroyable(double nodeId); @@ -82,8 +82,9 @@ SILKWORMAPI double Silkworm_ClothFillTriangleBuffer(double clothId, double leftU SILKWORMAPI double Silkworm_RopeCreate(double xPosition, double yPosition, double mass, double friction, double windFactor, double pushFactor, double tearThreshold); SILKWORMAPI double Silkworm_RopeAddNode(double ropeId, double xPosition, double yPosition, double length); SILKWORMAPI double Silkworm_RopeVerticalLength(double ropeId); -SILKWORMAPI double Silkworm_NearestX(double ropeId, double xPosition, double yPosition); -SILKWORMAPI double Silkworm_NearestY(double ropeId, double xPosition, double yPosition); +SILKWORMAPI double Silkworm_RopeNearestX(double ropeId, double xPosition, double yPosition); +SILKWORMAPI double Silkworm_RopeNearestY(double ropeId, double xPosition, double yPosition); +SILKWORMAPI void Silkworm_UnpinRope(double ropeId); SILKWORMAPI void Silkworm_RopeDestroy(double ropeId); SILKWORMAPI double Silkworm_RopeRequiredBufferSize(double ropeId); SILKWORMAPI double Silkworm_RopeFillBuffer(double ropeId, double width, double leftUV, double widthUV, double topUV, double heightUV);