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; float radius;
bool pinned; bool pinned;
float pushFactor; float pushFactor;
float windFactor;
bool destroyable; bool destroyable;
bool markedForDestroy; /* mutual recursion on nodes/links so this makes it easier to track destroys */ 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 typedef struct Silkworm_Cloth
{ {
uint64_t id; uint64_t id;
float windFactor;
uint32_t horizontalNodeCount; uint32_t horizontalNodeCount;
uint32_t verticalNodeCount; uint32_t verticalNodeCount;
@ -733,7 +733,7 @@ void Silkworm_Update(double deltaTime)
Silkworm_PerformDestroys(); 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)); Silkworm_Node* node = malloc(sizeof(Silkworm_Node));
uint64_t id; uint64_t id;
@ -766,6 +766,7 @@ double Silkworm_CreateNode(double xPosition, double yPosition, double mass, doub
node->friction = (float)friction; node->friction = (float)friction;
node->radius = (float)radius; node->radius = (float)radius;
node->pushFactor = (float)pushFactor; node->pushFactor = (float)pushFactor;
node->windFactor = (float)windFactor;
node->pinned = false; node->pinned = false;
node->destroyable = false; node->destroyable = false;
node->markedForDestroy = 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)); Silkworm_Cloth* cloth = malloc(sizeof(Silkworm_Cloth));
cloth->windFactor = (float)windFactor;
cloth->horizontalNodeCount = ((uint32_t)width / context->clothDensity) + 1; cloth->horizontalNodeCount = ((uint32_t)width / context->clothDensity) + 1;
cloth->verticalNodeCount = ((uint32_t)height / context->clothDensity) + 1; cloth->verticalNodeCount = ((uint32_t)height / context->clothDensity) + 1;
cloth->nodeIndices = malloc(sizeof(uint64_t*) * cloth->horizontalNodeCount); 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) 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; cloth->nodeIndices[i][j] = nodeId;
@ -1075,29 +1075,17 @@ void Silkworm_ClothFillNodeDataBuffer(double clothId)
void Silkworm_ApplyWind(double xSpeed, double ySpeed) void Silkworm_ApplyWind(double xSpeed, double ySpeed)
{ {
uint32_t i, j, k; uint32_t i;
Silkworm_Cloth* cloth;
Silkworm_Node* node; 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]; node->position.x += (float)xSpeed * 0.025f * node->windFactor;
node->position.y += (float)ySpeed * 0.025f * node->windFactor;
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;
}
}
}
} }
} }
} }
@ -1234,7 +1222,7 @@ double Silkworm_RopeAddNode(double ropeId, double xPosition, double yPosition, d
if (rope != NULL) 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 = realloc(rope->nodeIndices, sizeof(uint64_t) * (rope->nodeCount + 1));
rope->nodeIndices[rope->nodeCount] = nodeId; rope->nodeIndices[rope->nodeCount] = nodeId;
@ -1259,16 +1247,20 @@ double Silkworm_RopeVerticalLength(double ropeId)
if (rope != NULL) if (rope != NULL)
{ {
/* return the distance between the end node Y and the start Y */ Silkworm_Node* startNode = LookupNode(rope->nodeIndices[0]);
return LookupNode(rope->nodeIndices[rope->nodeCount - 1])->position.y - LookupNode(rope->nodeIndices[0])->position.y; Silkworm_Node* endNode = LookupNode(rope->nodeIndices[rope->nodeCount - 1]);
}
else if (startNode != NULL && endNode != NULL)
{ {
return -1; /* 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; uint32_t i;
float nearestSqrDistance, nearestX; float nearestSqrDistance, nearestX;
@ -1284,15 +1276,18 @@ double Silkworm_NearestX(double ropeId, double xPosition, double yPosition)
{ {
Silkworm_Node* node = LookupNode(rope->nodeIndices[i]); Silkworm_Node* node = LookupNode(rope->nodeIndices[i]);
float yDistance = node->position.y - yPosition; if (node != NULL)
float xDistance = node->position.x - xPosition;
float sqrDistance = xDistance * xDistance + yDistance * yDistance;
if (sqrDistance < nearestSqrDistance)
{ {
nearestSqrDistance = sqrDistance; float yDistance = node->position.y - yPosition;
nearestX = node->position.x; 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; return nearestX;
} }
double Silkworm_NearestY(double ropeId, double xPosition, double yPosition) double Silkworm_RopeNearestY(double ropeId, double xPosition, double yPosition)
{ {
uint32_t i; uint32_t i;
float nearestSqrDistance, nearestY; float nearestSqrDistance, nearestY;
@ -1316,15 +1311,18 @@ double Silkworm_NearestY(double ropeId, double xPosition, double yPosition)
{ {
Silkworm_Node* node = LookupNode(rope->nodeIndices[i]); Silkworm_Node* node = LookupNode(rope->nodeIndices[i]);
float yDistance = node->position.y - yPosition; if (node != NULL)
float xDistance = node->position.x - xPosition;
float sqrDistance = xDistance * xDistance + yDistance * yDistance;
if (sqrDistance < nearestSqrDistance)
{ {
nearestSqrDistance = sqrDistance; float yDistance = node->position.y - yPosition;
nearestY = node->position.y; 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; 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) double Silkworm_RopeCreate(double xPosition, double yPosition, double mass, double friction, double windFactor, double pushFactor, double tearThreshold)
{ {
Silkworm_Rope* rope = malloc(sizeof(Silkworm_Rope)); 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->nodeIndices = malloc(sizeof(uint64_t));
rope->nodeCount = 1; 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]); Silkworm_Node* node = LookupNode(rope->nodeIndices[0]);
node->pinned = true; node->pinned = true;
@ -1397,6 +1407,9 @@ void Silkworm_RopeDestroy(double ropeId)
} }
free(rope->nodeIndices); 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]; Silkworm_Node* node = context->nodes[i];
if (node != NULL) if (node != NULL && node->destroyable)
{ {
float xDistance = (float)fabs((float)x - node->position.x); float xDistance = (float)fabs((float)x - node->position.x);
float yDistance = (float)fabs((float)y - node->position.y); 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 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); 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_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_RopeAddNode(double ropeId, double xPosition, double yPosition, double length);
SILKWORMAPI double Silkworm_RopeVerticalLength(double ropeId); SILKWORMAPI double Silkworm_RopeVerticalLength(double ropeId);
SILKWORMAPI double Silkworm_NearestX(double ropeId, double xPosition, double yPosition); SILKWORMAPI double Silkworm_RopeNearestX(double ropeId, double xPosition, double yPosition);
SILKWORMAPI double Silkworm_NearestY(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 void Silkworm_RopeDestroy(double ropeId);
SILKWORMAPI double Silkworm_RopeRequiredBufferSize(double ropeId); SILKWORMAPI double Silkworm_RopeRequiredBufferSize(double ropeId);
SILKWORMAPI double Silkworm_RopeFillBuffer(double ropeId, double width, double leftUV, double widthUV, double topUV, double heightUV); SILKWORMAPI double Silkworm_RopeFillBuffer(double ropeId, double width, double leftUV, double widthUV, double topUV, double heightUV);