From 18b84ca0c4ea8c0858b7d3012173e49f6cb82f4e Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Fri, 24 Jun 2022 00:45:19 -0700 Subject: [PATCH] some API improvements --- src/Silkworm2.c | 191 +++++++++++++++++++++++++++++------------------- src/Silkworm2.h | 15 ++-- 2 files changed, 124 insertions(+), 82 deletions(-) diff --git a/src/Silkworm2.c b/src/Silkworm2.c index f3c9750..b7b3a2c 100644 --- a/src/Silkworm2.c +++ b/src/Silkworm2.c @@ -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; } diff --git a/src/Silkworm2.h b/src/Silkworm2.h index c827d10..66348ef 100644 --- a/src/Silkworm2.h +++ b/src/Silkworm2.h @@ -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);