some API improvements

main
cosmonaut 2022-06-24 00:45:19 -07:00
parent bad2d6b00b
commit 18b84ca0c4
2 changed files with 124 additions and 82 deletions

View File

@ -294,6 +294,13 @@ typedef struct Silkworm_Cloth
uint32_t horizontalNodeCount;
uint32_t verticalNodeCount;
float depth;
float leftUV;
float widthUV;
float topUV;
float heightUV;
/* note that the cloth doesn't own the nodes, just has pointers to them */
Silkworm_Node*** nodes; /* x by y grid of indices */
@ -350,6 +357,9 @@ typedef struct Silkworm_Context
Silkworm_Vector2* linkDestructionData;
uint32_t linkDestructionDataCount;
uint32_t linkDestructionDataCapacity;
Silkworm_Vertex* vertexBuffer;
uint32_t vertexCapacity;
} Silkworm_Context;
static Silkworm_Context *context = NULL;
@ -394,6 +404,9 @@ void Silkworm_Init()
context->linkDestructionDataCapacity = 16;
context->linkDestructionData = malloc(sizeof(Silkworm_Vector2) * context->nodeDestructionDataCapacity);
context->linkDestructionDataCount = 0;
context->vertexCapacity = 1024;
context->vertexBuffer = malloc(sizeof(Silkworm_Vertex) * context->vertexCapacity);
}
static inline Silkworm_Node* LookupNode(uint64_t nodeId)
@ -640,6 +653,22 @@ void Silkworm_Update(float delta, float windSpeedX, float windSpeedY)
context->nodeDestructionDataCount = 0;
context->linkDestructionDataCount = 0;
// apply wind
for (i = 0; i < context->nodeCount; i += 1)
{
node = context->nodes[i];
if (node != NULL)
{
if (!node->pinned)
{
node->position.x += (0.5f * sinf(context->timeElapsed * 4 + node->position.y / 2) + 0.5f) * windSpeedX * delta * 0.05f * node->windFactor;
node->position.y += (0.5f * sinf(context->timeElapsed * 4 + node->position.x / 3) + 0.5f) * windSpeedY * delta * 0.05f * node->windFactor;
}
}
}
// solve constraints
for (i = 0; i < CONSTRAINT_ITERATION_COUNT; i += 1)
{
for (j = 0; j < context->linkCount; j += 1)
@ -657,9 +686,9 @@ void Silkworm_Update(float delta, float windSpeedX, float windSpeedY)
float translateX = diffX * 0.5f * difference;
float translateY = diffY * 0.5f * difference;
float distanceMoved = (float)sqrt(translateX * translateX + translateY * translateY);
float distanceMovedSquared = translateX * translateX + translateY * translateY;
if (distanceMoved > link->tearThreshold)
if (distanceMovedSquared > link->tearThreshold * link->tearThreshold)
{
Silkworm_DestroyLink((double)link->id);
}
@ -681,6 +710,7 @@ void Silkworm_Update(float delta, float windSpeedX, float windSpeedY)
}
}
// update node positions
for (j = 0; j < context->nodeCount; j += 1)
{
node = context->nodes[j];
@ -701,9 +731,6 @@ void Silkworm_Update(float delta, float windSpeedX, float windSpeedY)
node->position.x += velocityX + accelerationX;
node->position.y += velocityY + accelerationY;
node->position.x += (0.5f * sinf(context->timeElapsed * 4 + node->position.y / 2) + 0.5f) * windSpeedX * 0.05f * node->windFactor;
node->position.y += (0.5f * sinf(context->timeElapsed * 4 + node->position.x / 3) + 0.5f) * windSpeedY * 0.05f * node->windFactor;
node->velocity.x = velocityX * delta;
node->velocity.y = velocityY * delta;
@ -842,8 +869,9 @@ void* Silkworm_ClothCreate(Silkworm_ClothCreateInfo* clothCreateInfo)
Silkworm_Cloth* cloth = malloc(sizeof(Silkworm_Cloth));
cloth->horizontalNodeCount = ((uint32_t)clothCreateInfo->horizontalNodeCount / context->clothDensity) + 1;
cloth->verticalNodeCount = ((uint32_t)clothCreateInfo->verticalNodeCount / context->clothDensity) + 1;
cloth->horizontalNodeCount = (uint32_t)clothCreateInfo->horizontalNodeCount;
cloth->verticalNodeCount = (uint32_t)clothCreateInfo->verticalNodeCount;
cloth->nodes = malloc(sizeof(Silkworm_Node**) * cloth->horizontalNodeCount);
uint64_t id;
@ -898,11 +926,6 @@ void* Silkworm_ClothCreate(Silkworm_ClothCreateInfo* clothCreateInfo)
cloth->nodes[i][j] = node;
if (j == 0)
{
node->pinned = true;
}
node->destroyable = true;
node->clothReference.clothId = cloth->id;
@ -1024,90 +1047,102 @@ void* Silkworm_ClothCreate(Silkworm_ClothCreateInfo* clothCreateInfo)
}
}
cloth->depth = clothCreateInfo->z;
cloth->leftUV = clothCreateInfo->leftUV;
cloth->widthUV = clothCreateInfo->rightUV - clothCreateInfo->leftUV;
cloth->topUV = clothCreateInfo->topUV;
cloth->heightUV = clothCreateInfo->bottomUV - clothCreateInfo->topUV;
return (void*) cloth;
}
/* FIXME: this is very unsafe */
double Silkworm_ClothHorizontalNodeCount(double clothId)
uint32_t Silkworm_ClothRender(void **pVertexBuffer, uint32_t *pVertexBufferLengthInBytes)
{
return context->cloths[(uint32_t)clothId]->horizontalNodeCount;
}
double Silkworm_ClothVerticalNodeCount(double clothId)
{
return context->cloths[(uint32_t)clothId]->verticalNodeCount;
}
int32_t Silkworm_ClothFillTriangleBuffer(void* clothPtr, void* vertexBufferPtr, float depth, float leftUV, float widthUV, float topUV, float heightUV)
{
uint32_t i, vertexCount;
Silkworm_Cloth* cloth = (Silkworm_Cloth*) clothPtr;
Silkworm_Vertex* vertexBuffer = (Silkworm_Vertex*) vertexBufferPtr;
uint32_t i, j, vertexCount;
vertexCount = 0;
for (i = 0; i < cloth->triangleCount; i += 1)
for (j = 0; j < context->clothCount; j += 1)
{
if (cloth->triangles[i] != NULL)
Silkworm_Cloth* cloth = context->cloths[j];
if (cloth != NULL)
{
if (cloth->triangles[i]->orientation == UpperLeft)
if (vertexCount + (cloth->triangleCount * 3) > context->vertexCapacity)
{
float left = leftUV + widthUV * ((float)cloth->triangles[i]->aHorizontalIndex / (cloth->horizontalNodeCount - 1));
float right = leftUV + widthUV * ((float)cloth->triangles[i]->bHorizontalIndex / (cloth->horizontalNodeCount - 1));
float top = topUV + heightUV * ((float)cloth->triangles[i]->aVerticalIndex / (cloth->verticalNodeCount - 1));
float bottom = topUV + heightUV * ((float)cloth->triangles[i]->cVerticalIndex / (cloth->verticalNodeCount - 1));
vertexBuffer[vertexCount].x = cloth->triangles[i]->a->position.x;
vertexBuffer[vertexCount].y = cloth->triangles[i]->a->position.y;
vertexBuffer[vertexCount].z = depth;
vertexBuffer[vertexCount].u = left;
vertexBuffer[vertexCount].v = top;
vertexBuffer[vertexCount + 1].x = cloth->triangles[i]->b->position.x;
vertexBuffer[vertexCount + 1].y = cloth->triangles[i]->b->position.y;
vertexBuffer[vertexCount + 1].z = depth;
vertexBuffer[vertexCount + 1].u = right;
vertexBuffer[vertexCount + 1].v = top;
vertexBuffer[vertexCount + 2].x = cloth->triangles[i]->c->position.x;
vertexBuffer[vertexCount + 2].y = cloth->triangles[i]->c->position.y;
vertexBuffer[vertexCount + 2].z = depth;
vertexBuffer[vertexCount + 2].u = left;
vertexBuffer[vertexCount + 2].v = bottom;
vertexCount += 3;
context->vertexCapacity *= 2;
context->vertexBuffer = realloc(context->vertexBuffer, sizeof(Silkworm_Vertex) * context->vertexCapacity);
}
else if (cloth->triangles[i]->orientation == BottomRight)
for (i = 0; i < cloth->triangleCount; i += 1)
{
float left = leftUV + widthUV * ((float)cloth->triangles[i]->bHorizontalIndex / (cloth->horizontalNodeCount - 1));
float right = leftUV + widthUV * ((float)cloth->triangles[i]->aHorizontalIndex / (cloth->horizontalNodeCount - 1));
if (cloth->triangles[i] != NULL)
{
if (cloth->triangles[i]->orientation == UpperLeft)
{
float left = cloth->leftUV + cloth->widthUV * ((float)cloth->triangles[i]->aHorizontalIndex / (cloth->horizontalNodeCount - 1));
float right = cloth->leftUV + cloth->widthUV * ((float)cloth->triangles[i]->bHorizontalIndex / (cloth->horizontalNodeCount - 1));
float top = topUV + heightUV * ((float)cloth->triangles[i]->cVerticalIndex / (cloth->verticalNodeCount - 1));
float bottom = topUV + heightUV * ((float)cloth->triangles[i]->aVerticalIndex / (cloth->verticalNodeCount - 1));
float top = cloth->topUV + cloth->heightUV * ((float)cloth->triangles[i]->aVerticalIndex / (cloth->verticalNodeCount - 1));
float bottom = cloth->topUV + cloth->heightUV * ((float)cloth->triangles[i]->cVerticalIndex / (cloth->verticalNodeCount - 1));
vertexBuffer[vertexCount].x = cloth->triangles[i]->a->position.x;
vertexBuffer[vertexCount].y = cloth->triangles[i]->a->position.y;
vertexBuffer[vertexCount].z = depth;
vertexBuffer[vertexCount].u = right;
vertexBuffer[vertexCount].v = bottom;
context->vertexBuffer[vertexCount].x = cloth->triangles[i]->a->position.x;
context->vertexBuffer[vertexCount].y = cloth->triangles[i]->a->position.y;
context->vertexBuffer[vertexCount].z = cloth->depth;
context->vertexBuffer[vertexCount].u = left;
context->vertexBuffer[vertexCount].v = top;
vertexBuffer[vertexCount + 1].x = cloth->triangles[i]->b->position.x;
vertexBuffer[vertexCount + 1].y = cloth->triangles[i]->b->position.y;
vertexBuffer[vertexCount + 1].z = depth;
vertexBuffer[vertexCount + 1].u = left;
vertexBuffer[vertexCount + 1].v = bottom;
context->vertexBuffer[vertexCount + 1].x = cloth->triangles[i]->b->position.x;
context->vertexBuffer[vertexCount + 1].y = cloth->triangles[i]->b->position.y;
context->vertexBuffer[vertexCount + 1].z = cloth->depth;
context->vertexBuffer[vertexCount + 1].u = right;
context->vertexBuffer[vertexCount + 1].v = top;
vertexBuffer[vertexCount + 2].x = cloth->triangles[i]->c->position.x;
vertexBuffer[vertexCount + 2].y = cloth->triangles[i]->c->position.y;
vertexBuffer[vertexCount + 2].z = depth;
vertexBuffer[vertexCount + 2].u = right;
vertexBuffer[vertexCount + 2].v = top;
context->vertexBuffer[vertexCount + 2].x = cloth->triangles[i]->c->position.x;
context->vertexBuffer[vertexCount + 2].y = cloth->triangles[i]->c->position.y;
context->vertexBuffer[vertexCount + 2].z = cloth->depth;
context->vertexBuffer[vertexCount + 2].u = left;
context->vertexBuffer[vertexCount + 2].v = bottom;
vertexCount += 3;
vertexCount += 3;
}
else if (cloth->triangles[i]->orientation == BottomRight)
{
float left = cloth->leftUV + cloth->widthUV * ((float)cloth->triangles[i]->bHorizontalIndex / (cloth->horizontalNodeCount - 1));
float right = cloth->leftUV + cloth->widthUV * ((float)cloth->triangles[i]->aHorizontalIndex / (cloth->horizontalNodeCount - 1));
float top = cloth->topUV + cloth->heightUV * ((float)cloth->triangles[i]->cVerticalIndex / (cloth->verticalNodeCount - 1));
float bottom = cloth->topUV + cloth->heightUV * ((float)cloth->triangles[i]->aVerticalIndex / (cloth->verticalNodeCount - 1));
context->vertexBuffer[vertexCount].x = cloth->triangles[i]->a->position.x;
context->vertexBuffer[vertexCount].y = cloth->triangles[i]->a->position.y;
context->vertexBuffer[vertexCount].z = cloth->depth;
context->vertexBuffer[vertexCount].u = right;
context->vertexBuffer[vertexCount].v = bottom;
context->vertexBuffer[vertexCount + 1].x = cloth->triangles[i]->b->position.x;
context->vertexBuffer[vertexCount + 1].y = cloth->triangles[i]->b->position.y;
context->vertexBuffer[vertexCount + 1].z = cloth->depth;
context->vertexBuffer[vertexCount + 1].u = left;
context->vertexBuffer[vertexCount + 1].v = bottom;
context->vertexBuffer[vertexCount + 2].x = cloth->triangles[i]->c->position.x;
context->vertexBuffer[vertexCount + 2].y = cloth->triangles[i]->c->position.y;
context->vertexBuffer[vertexCount + 2].z = cloth->depth;
context->vertexBuffer[vertexCount + 2].u = right;
context->vertexBuffer[vertexCount + 2].v = top;
vertexCount += 3;
}
}
}
}
}
*pVertexBuffer = context->vertexBuffer;
*pVertexBufferLengthInBytes = sizeof(Silkworm_Vertex) * vertexCount;
}
return vertexCount;
}
@ -1288,6 +1323,8 @@ void Silkworm_Finish()
free(context->nodeDestructionData);
free(context->linkDestructionData);
free(context->vertexBuffer);
free(context);
context = NULL;
}

View File

@ -58,8 +58,8 @@ extern "C" {
typedef struct Silkworm_NodeCreateInfo
{
int32_t x;
int32_t y;
float x;
float y;
float mass;
float friction;
float radius;
@ -71,14 +71,19 @@ typedef struct Silkworm_NodeCreateInfo
typedef struct Silkworm_ClothCreateInfo
{
int32_t x;
int32_t y;
float x;
float y;
float z;
int32_t horizontalNodeCount;
int32_t verticalNodeCount;
float mass;
float friction;
float windFactor;
float tearThreshold;
float leftUV;
float topUV;
float rightUV;
float bottomUV;
} Silkworm_ClothCreateInfo;
typedef struct Silkworm_Vertex
@ -102,7 +107,7 @@ SILKWORMAPI void* Silkworm_ClothCreate(Silkworm_ClothCreateInfo* clothCreateInfo
SILKWORMAPI void Silkworm_ClothNodePin(void* clothPtr, uint32_t i, uint32_t j);
SILKWORMAPI void Silkworm_ClothNodeUnpin(void* clothPtr, uint32_t i, uint32_t j);
SILKWORMAPI void Silkworm_ClothNodeDestroy(void* clothPtr, uint32_t i, uint32_t j);
SILKWORMAPI int32_t Silkworm_ClothFillTriangleBuffer(void* clothPtr, void* vertexBufferPtr, float depth, float leftUV, float widthUV, float topUV, float heightUV);
SILKWORMAPI uint32_t Silkworm_ClothRender(void **pVertexBuffer, uint32_t *pVertexBufferLengthInBytes);
SILKWORMAPI void Silkworm_ClothDestroy(void* clothPtr);
SILKWORMAPI void Silkworm_PinNodesInRadius(float x, float y, float radius);