more features

main
cosmonaut 2021-09-25 03:47:40 -07:00
parent 95c89d3ce1
commit 26516c9829
3 changed files with 201 additions and 9 deletions

View File

@ -47,7 +47,7 @@ typedef struct Silkworm_Node
float mass;
float friction;
float radius;
float pinned;
bool pinned;
float pushFactor;
bool destroyable;
@ -413,7 +413,10 @@ void Silkworm_Internal_DestroyCloth(Silkworm_Cloth* cloth)
{
free(cloth->nodeHash.buckets[i].elements[j].indexArray);
}
free(cloth->nodeHash.buckets[i].elements);
if (cloth->nodeHash.buckets[i].elements != NULL)
{
free(cloth->nodeHash.buckets[i].elements);
}
}
for (i = 0; i < NUM_LINK_TRIANGLE_HASH_BUCKETS; i += 1)
@ -422,7 +425,10 @@ void Silkworm_Internal_DestroyCloth(Silkworm_Cloth* cloth)
{
free(cloth->linkHash.buckets[i].elements[j].indexArray);
}
free(cloth->linkHash.buckets[i].elements);
if (cloth->linkHash.buckets[i].elements != NULL)
{
free(cloth->linkHash.buckets[i].elements);
}
}
for (i = 0; i < cloth->horizontalNodeCount; i += 1)
@ -434,7 +440,15 @@ void Silkworm_Internal_DestroyCloth(Silkworm_Cloth* cloth)
free(cloth->nodeIndices[i]);
}
free(cloth->nodeIndices);
free(cloth);
for (i = 0; i < cloth->triangleCount; i += 1)
{
if (cloth->triangles[i] != NULL)
{
free(cloth->triangles[i]);
}
}
free(cloth->triangles);
if (context->clothIndexStackCount >= context->clothIndexStackCapacity)
{
@ -444,6 +458,8 @@ void Silkworm_Internal_DestroyCloth(Silkworm_Cloth* cloth)
context->clothIndexStack[context->clothIndexStackCount] = cloth->id;
context->clothIndexStackCount += 1;
free(cloth);
}
void Silkworm_DestroyCloth(double clothId)
@ -940,6 +956,47 @@ double Silkworm_CreateCloth(double xPosition, double yPosition, double width, do
return (double)cloth->id;
}
/* FIXME: this is very unsafe */
double Silkworm_ClothHorizontalNodeCount(double clothId)
{
return context->cloths[(uint32_t)clothId]->horizontalNodeCount;
}
double Silkworm_ClothVerticalNodeCount(double clothId)
{
return context->cloths[(uint32_t)clothId]->verticalNodeCount;
}
void Silkworm_ClothFillNodeDataBuffer(double clothId)
{
uint32_t i, j;
uint8_t* bufferAddress = context->currentBufferAddress;
Silkworm_Cloth* cloth = LookupCloth(clothId);
uint8_t active = 0;
uint8_t pinned = 0;
for (i = 0; i < cloth->horizontalNodeCount; i += 1)
{
for (j = 0; j < cloth->verticalNodeCount; j += 1)
{
active = context->nodes[cloth->nodeIndices[i][j]] != NULL;
memcpy(bufferAddress, &active, sizeof(uint8_t));
bufferAddress += sizeof(uint8_t);
pinned = 0;
if (context->nodes[cloth->nodeIndices[i][j]] != NULL)
{
pinned = context->nodes[cloth->nodeIndices[i][j]]->pinned;
}
memcpy(bufferAddress, &pinned, sizeof(uint8_t));
bufferAddress += sizeof(uint8_t);
}
}
}
void Silkworm_ApplyWind(double xSpeed, double ySpeed)
{
uint32_t i, j, k;
@ -969,7 +1026,7 @@ void Silkworm_ApplyWind(double xSpeed, double ySpeed)
}
}
void Silkworm_SetTriangleBuffer(const char* bufferId)
void Silkworm_SetBuffer(const char* bufferId)
{
context->currentBufferAddress = (uint8_t*)bufferId;
}
@ -1218,6 +1275,19 @@ double Silkworm_FillEditorBuffer()
if (node != NULL)
{
if (node->pinned)
{
color.r = 255;
color.g = 255;
color.b = 0;
}
else
{
color.r = 255;
color.g = 0;
color.b = 0;
}
/* top left triangle */
position.x = node->position.x - node->radius;
position.y = node->position.y - node->radius;
@ -1293,7 +1363,7 @@ void Silkworm_PushNodesInRadius(double x, double y, double radius, double xDirec
{
Silkworm_Node* node = context->nodes[i];
if (node != NULL)
if (node != NULL && !node->pinned)
{
float xDistance = (float)fabs((float)x - node->position.x);
float yDistance = (float)fabs((float)y - node->position.y);
@ -1309,6 +1379,56 @@ void Silkworm_PushNodesInRadius(double x, double y, double radius, double xDirec
}
}
void Silkworm_PinNodesInRadius(double x, double y, double radius)
{
/* TODO: spatial hash implementation */
uint32_t i;
for (i = 0; i < context->nodeCount; i += 1)
{
Silkworm_Node* node = context->nodes[i];
if (node != NULL)
{
float xDistance = (float)fabs((float)x - node->position.x);
float yDistance = (float)fabs((float)y - node->position.y);
float squareDistance = xDistance * xDistance + yDistance * yDistance;
if (squareDistance <= radius * radius)
{
node->pinned = true;
}
}
}
}
void Silkworm_UnpinNodesInRadius(double x, double y, double radius)
{
/* TODO: spatial hash implementation */
uint32_t i;
for (i = 0; i < context->nodeCount; i += 1)
{
Silkworm_Node* node = context->nodes[i];
if (node != NULL)
{
float xDistance = (float)fabs((float)x - node->position.x);
float yDistance = (float)fabs((float)y - node->position.y);
float squareDistance = xDistance * xDistance + yDistance * yDistance;
if (squareDistance <= radius * radius)
{
node->pinned = false;
}
}
}
}
void Silkworm_DestroyNodesInRadius(double x, double y, double radius)
{
/* TODO: spatial hash implementation */
@ -1332,6 +1452,54 @@ void Silkworm_DestroyNodesInRadius(double x, double y, double radius)
}
}
}
Silkworm_PerformDestroys();
}
double Silkworm_DestroyClothInRadius(double x, double y, double radius)
{
/* TODO: spatial hash implementation */
uint32_t i, j;
double clothId = -1;
for (i = 0; i < context->nodeCount; i += 1)
{
Silkworm_Node* node = context->nodes[i];
if (node != NULL)
{
float xDistance = (float)fabs((float)x - node->position.x);
float yDistance = (float)fabs((float)y - node->position.y);
float squareDistance = xDistance * xDistance + yDistance * yDistance;
if (squareDistance <= radius * radius)
{
for (j = 0; j < context->clothCount; j += 1)
{
Silkworm_Cloth* cloth = context->cloths[j];
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 = (double)cloth->id;
Silkworm_Internal_DestroyCloth(cloth);
break;
}
}
}
}
}
}
Silkworm_PerformDestroys();
return clothId;
}
void Silkworm_ClearAll()
@ -1348,3 +1516,19 @@ void Silkworm_ClearAll()
Silkworm_PerformDestroys();
}
void Silkworm_Finish()
{
Silkworm_ClearAll();
free(context->nodes);
free(context->links);
free(context->cloths);
free(context->nodeIndexStack);
free(context->linkIndexStack);
free(context->clothIndexStack);
free(context);
context = NULL;
}

View File

@ -60,19 +60,23 @@ SILKWORMAPI void Silkworm_Init();
SILKWORMAPI void Silkworm_Update(double delta);
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 void Silkworm_NodeSetDestroyable(double nodeId);
SILKWORMAPI double Silkworm_CreateLink(double aId, double bId, double distance, double tearThreshold);
SILKWORMAPI double Silkworm_CreateCloth(double xPosition, double yPosition, double horizontalNodeCount, double verticalNodeCount, double mass, double friction, double windFactor, double tearThreshold);
SILKWORMAPI double Silkworm_CreateCloth(double xPosition, double yPosition, double width, double height, double mass, double friction, double windFactor, double tearThreshold);
SILKWORMAPI double Silkworm_ClothHorizontalNodeCount(double clothId);
SILKWORMAPI double Silkworm_ClothVerticalNodeCount(double clothId);
SILKWORMAPI void Silkworm_ClothNodePin(double clothId, double i, double j);
SILKWORMAPI void Silkworm_ClothNodeUnpin(double clothId, double i, double j);
SILKWORMAPI void Silkworm_ClothNodeDestroy(double clothId, double i, double j);
SILKWORMAPI void Silkworm_ClothFillNodeDataBuffer(double clothId);
SILKWORMAPI void Silkworm_DestroyCloth(double clothId);
SILKWORMAPI void Silkworm_SetTriangleBuffer(const char* bufferId);
SILKWORMAPI double Silkworm_ClothFillTriangleBuffer(double clothId, double leftUV, double widthUV, double topUV, double heightUV);
SILKWORMAPI double Silkworm_GetEditorBufferRequiredSize();
@ -80,9 +84,13 @@ SILKWORMAPI double Silkworm_FillEditorBuffer();
SILKWORMAPI void Silkworm_DestroyNode(double nodeId);
SILKWORMAPI void Silkworm_PinNodesInRadius(double x, double y, double radius);
SILKWORMAPI void Silkworm_UnpinNodesInRadius(double x, double y, double radius);
SILKWORMAPI void Silkworm_PushNodesInRadius(double x, double y, double radius, double xDirection, double yDirection);
SILKWORMAPI void Silkworm_DestroyNodesInRadius(double x, double y, double radius);
SILKWORMAPI double Silkworm_DestroyClothInRadius(double x, double y, double radius);
SILKWORMAPI void Silkworm_ClearAll();
SILKWORMAPI void Silkworm_Finish();
#endif /* SILKWORM_H */

View File

@ -19,7 +19,7 @@
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{6DB15344-E000-45CB-A48A-1D72F7D6E945}</ProjectGuid>
<ProjectGuid>{4F20502A-F926-4D12-872D-64AC2E065078}</ProjectGuid>
<RootNamespace>Silkworm</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>