change rope and cloth to use pointers to nodes instead of indices

main
cosmonaut 2021-09-30 22:50:32 -07:00
parent 5f018e76ba
commit da4062c30e
1 changed files with 143 additions and 73 deletions

View File

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