various rope fixes

main
cosmonaut 2021-09-30 15:47:56 -07:00
parent 4a21f5eba8
commit 8d298e84a0
2 changed files with 67 additions and 53 deletions

View File

@ -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);

View File

@ -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);