rope tech
parent
b96860705d
commit
0c0d1b67f5
390
src/Silkworm.c
390
src/Silkworm.c
|
@ -29,12 +29,33 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define PI 3.14159265358979323846
|
||||
|
||||
typedef struct Silkworm_Vector2
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
} Silkworm_Vector2;
|
||||
|
||||
static inline Silkworm_Vector2 Vector2_Rotate(Silkworm_Vector2 vector, float angle)
|
||||
{
|
||||
Silkworm_Vector2 rotated;
|
||||
rotated.x = vector.x * cosf(angle) - vector.y * sinf(angle);
|
||||
rotated.y = vector.x * sinf(angle) + vector.y * cosf(angle);
|
||||
return rotated;
|
||||
}
|
||||
|
||||
static inline Silkworm_Vector2 Vector2_Normalize(Silkworm_Vector2 vector)
|
||||
{
|
||||
float length = sqrtf(vector.x * vector.x + vector.y * vector.y);
|
||||
|
||||
Silkworm_Vector2 normalized;
|
||||
normalized.x = vector.x / length;
|
||||
normalized.y = vector.y / length;
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
typedef struct Silkworm_Link Silkworm_Link;
|
||||
|
||||
typedef struct Silkworm_Node
|
||||
|
@ -275,9 +296,16 @@ typedef struct Silkworm_Cloth
|
|||
|
||||
typedef struct Silkworm_Rope
|
||||
{
|
||||
uint64_t id;
|
||||
|
||||
uint64_t* nodeIndices;
|
||||
uint32_t nodeCount;
|
||||
|
||||
uint32_t* nodeIndices;
|
||||
float windFactor;
|
||||
float nodeMass;
|
||||
float tearThreshold;
|
||||
float friction;
|
||||
float pushFactor;
|
||||
} Silkworm_Rope;
|
||||
|
||||
typedef struct Silkworm_Color
|
||||
|
@ -298,7 +326,9 @@ typedef struct Silkworm_Context
|
|||
|
||||
Silkworm_Cloth** cloths;
|
||||
uint32_t clothCount;
|
||||
uint32_t clothCapacity;
|
||||
|
||||
Silkworm_Rope** ropes;
|
||||
uint32_t ropeCount;
|
||||
|
||||
uint64_t* nodeIndexStack;
|
||||
uint32_t nodeIndexStackCount;
|
||||
|
@ -312,6 +342,10 @@ typedef struct Silkworm_Context
|
|||
uint32_t clothIndexStackCount;
|
||||
uint32_t clothIndexStackCapacity;
|
||||
|
||||
uint64_t* ropeIndexStack;
|
||||
uint32_t ropeIndexStackCount;
|
||||
uint32_t ropeIndexStackCapacity;
|
||||
|
||||
float gravity;
|
||||
float xBound;
|
||||
float yBound;
|
||||
|
@ -346,6 +380,9 @@ void Silkworm_Init()
|
|||
context->cloths = NULL;
|
||||
context->clothCount = 0;
|
||||
|
||||
context->ropes = NULL;
|
||||
context->ropeCount = 0;
|
||||
|
||||
context->nodeIndexStackCapacity = 16;
|
||||
context->nodeIndexStack = malloc(sizeof(uint64_t) * context->nodeIndexStackCapacity);
|
||||
context->nodeIndexStackCount = 0;
|
||||
|
@ -358,6 +395,10 @@ void Silkworm_Init()
|
|||
context->clothIndexStack = malloc(sizeof(uint64_t) * context->clothIndexStackCapacity);
|
||||
context->clothIndexStackCount = 0;
|
||||
|
||||
context->ropeIndexStackCapacity = 16;
|
||||
context->ropeIndexStack = malloc(sizeof(uint64_t) * context->ropeIndexStackCapacity);
|
||||
context->ropeIndexStackCount = 0;
|
||||
|
||||
context->gravity = 200;
|
||||
context->xBound = 1000;
|
||||
context->yBound = 1000;
|
||||
|
@ -434,61 +475,64 @@ void Silkworm_Internal_DestroyCloth(Silkworm_Cloth* cloth)
|
|||
{
|
||||
uint32_t i, j;
|
||||
|
||||
context->cloths[cloth->id] = NULL;
|
||||
|
||||
for (i = 0; i < NUM_NODE_TRIANGLE_HASH_BUCKETS; i += 1)
|
||||
if (cloth != NULL)
|
||||
{
|
||||
for (j = 0; j < cloth->nodeHash.buckets[i].count; j += 1)
|
||||
context->cloths[cloth->id] = NULL;
|
||||
|
||||
for (i = 0; i < NUM_NODE_TRIANGLE_HASH_BUCKETS; i += 1)
|
||||
{
|
||||
free(cloth->nodeHash.buckets[i].elements[j].indexArray);
|
||||
for (j = 0; j < cloth->nodeHash.buckets[i].count; j += 1)
|
||||
{
|
||||
free(cloth->nodeHash.buckets[i].elements[j].indexArray);
|
||||
}
|
||||
if (cloth->nodeHash.buckets[i].elements != NULL)
|
||||
{
|
||||
free(cloth->nodeHash.buckets[i].elements);
|
||||
}
|
||||
}
|
||||
if (cloth->nodeHash.buckets[i].elements != NULL)
|
||||
|
||||
for (i = 0; i < NUM_LINK_TRIANGLE_HASH_BUCKETS; i += 1)
|
||||
{
|
||||
free(cloth->nodeHash.buckets[i].elements);
|
||||
for (j = 0; j < cloth->linkHash.buckets[i].count; j += 1)
|
||||
{
|
||||
free(cloth->linkHash.buckets[i].elements[j].indexArray);
|
||||
}
|
||||
if (cloth->linkHash.buckets[i].elements != NULL)
|
||||
{
|
||||
free(cloth->linkHash.buckets[i].elements);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < cloth->horizontalNodeCount; i += 1)
|
||||
{
|
||||
for (j = 0; j < cloth->verticalNodeCount; j += 1)
|
||||
{
|
||||
Silkworm_DestroyNode((double)cloth->nodeIndices[i][j]);
|
||||
}
|
||||
free(cloth->nodeIndices[i]);
|
||||
}
|
||||
free(cloth->nodeIndices);
|
||||
|
||||
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)
|
||||
{
|
||||
context->clothIndexStackCapacity *= 2;
|
||||
context->nodeIndexStack = realloc(context->nodeIndexStack, sizeof(uint64_t) * context->nodeIndexStackCapacity);
|
||||
}
|
||||
|
||||
context->clothIndexStack[context->clothIndexStackCount] = cloth->id;
|
||||
context->clothIndexStackCount += 1;
|
||||
|
||||
free(cloth);
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_LINK_TRIANGLE_HASH_BUCKETS; i += 1)
|
||||
{
|
||||
for (j = 0; j < cloth->linkHash.buckets[i].count; j += 1)
|
||||
{
|
||||
free(cloth->linkHash.buckets[i].elements[j].indexArray);
|
||||
}
|
||||
if (cloth->linkHash.buckets[i].elements != NULL)
|
||||
{
|
||||
free(cloth->linkHash.buckets[i].elements);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < cloth->horizontalNodeCount; i += 1)
|
||||
{
|
||||
for (j = 0; j < cloth->verticalNodeCount; j += 1)
|
||||
{
|
||||
Silkworm_DestroyNode((double)cloth->nodeIndices[i][j]);
|
||||
}
|
||||
free(cloth->nodeIndices[i]);
|
||||
}
|
||||
free(cloth->nodeIndices);
|
||||
|
||||
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)
|
||||
{
|
||||
context->clothIndexStackCapacity *= 2;
|
||||
context->nodeIndexStack = realloc(context->nodeIndexStack, sizeof(uint64_t) * context->nodeIndexStackCapacity);
|
||||
}
|
||||
|
||||
context->clothIndexStack[context->clothIndexStackCount] = cloth->id;
|
||||
context->clothIndexStackCount += 1;
|
||||
|
||||
free(cloth);
|
||||
}
|
||||
|
||||
void Silkworm_DestroyCloth(double clothId)
|
||||
|
@ -859,7 +903,7 @@ double Silkworm_CreateCloth(double xPosition, double yPosition, double width, do
|
|||
|
||||
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, 0.5);
|
||||
uint64_t nodeId = (uint64_t) Silkworm_CreateNode(xPosition + i * context->clothDensity, yPosition + j * context->clothDensity, mass, friction, 1, 1.0);
|
||||
|
||||
cloth->nodeIndices[i][j] = nodeId;
|
||||
|
||||
|
@ -1179,6 +1223,234 @@ 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);
|
||||
|
||||
double nodeId = Silkworm_CreateNode(xPosition, yPosition, rope->nodeMass, rope->friction, 1.0, rope->pushFactor);
|
||||
|
||||
rope->nodeIndices = realloc(rope->nodeIndices, sizeof(uint64_t) * (rope->nodeCount + 1));
|
||||
rope->nodeIndices[rope->nodeCount] = nodeId;
|
||||
rope->nodeCount += 1;
|
||||
|
||||
Silkworm_Node* node = LookupNode((uint64_t)nodeId);
|
||||
node->destroyable = false;
|
||||
|
||||
Silkworm_CreateLink((double)rope->nodeIndices[rope->nodeCount - 2], (double)rope->nodeIndices[rope->nodeCount - 1], length, rope->tearThreshold);
|
||||
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
double Silkworm_RopeCreate(double xPosition, double yPosition, double mass, double friction, double windFactor, double pushFactor, double tearThreshold)
|
||||
{
|
||||
Silkworm_Rope* rope = malloc(sizeof(Silkworm_Rope));
|
||||
|
||||
uint64_t id;
|
||||
|
||||
if (context->ropeIndexStackCount > 0)
|
||||
{
|
||||
id = context->ropeIndexStack[context->ropeIndexStackCount - 1];
|
||||
context->ropeIndexStackCount -= 1;
|
||||
|
||||
context->ropes[id] = rope;
|
||||
}
|
||||
else
|
||||
{
|
||||
id = context->ropeCount;
|
||||
|
||||
context->ropes = realloc(context->ropes, sizeof(Silkworm_Rope*) * (context->ropeCount + 1));
|
||||
context->ropes[id] = rope;
|
||||
context->ropeCount += 1;
|
||||
}
|
||||
|
||||
rope->id = id;
|
||||
|
||||
rope->nodeMass = mass;
|
||||
rope->friction = friction;
|
||||
rope->windFactor = windFactor;
|
||||
rope->tearThreshold = tearThreshold;
|
||||
rope->pushFactor = pushFactor;
|
||||
|
||||
// TODO: create first node here
|
||||
rope->nodeIndices = malloc(sizeof(uint64_t));
|
||||
rope->nodeCount = 1;
|
||||
|
||||
rope->nodeIndices[0] = Silkworm_CreateNode(xPosition, yPosition, rope->nodeMass, rope->friction, 1.0, rope->pushFactor);
|
||||
|
||||
Silkworm_Node* node = LookupNode(rope->nodeIndices[0]);
|
||||
node->pinned = true;
|
||||
node->destroyable = false;
|
||||
|
||||
return (double)rope->id;
|
||||
}
|
||||
|
||||
void Silkworm_RopeDestroy(double ropeId)
|
||||
{
|
||||
uint32_t i;
|
||||
Silkworm_Rope *rope = LookupRope(ropeId);
|
||||
|
||||
if (rope != NULL)
|
||||
{
|
||||
if (context->ropeIndexStackCount >= context->ropeIndexStackCapacity)
|
||||
{
|
||||
context->ropeIndexStackCapacity *= 2;
|
||||
context->ropeIndexStack = realloc(context->ropeIndexStack, sizeof(uint64_t) * context->ropeIndexStackCapacity);
|
||||
}
|
||||
|
||||
context->ropeIndexStack[context->ropeIndexStackCount] = rope->id;
|
||||
context->ropeIndexStackCount += 1;
|
||||
|
||||
for (i = 0; i < rope->nodeCount; i += 1)
|
||||
{
|
||||
Silkworm_DestroyNode((double)rope->nodeIndices[i]);
|
||||
}
|
||||
|
||||
free(rope->nodeIndices);
|
||||
}
|
||||
}
|
||||
|
||||
double Silkworm_RopeRequiredBufferSize(double ropeId)
|
||||
{
|
||||
Silkworm_Rope* rope = LookupRope(ropeId);
|
||||
return (double)(rope->nodeCount - 1) * 6 * (sizeof(Silkworm_Vector2) + sizeof(Silkworm_Color) + (sizeof(float) * 2));
|
||||
}
|
||||
|
||||
double Silkworm_RopeFillBuffer(double ropeId, double width, double leftUV, double widthUV, double topUV, double heightUV)
|
||||
{
|
||||
uint32_t i, vertexCount;
|
||||
Silkworm_Rope* rope = LookupRope(ropeId);
|
||||
uint8_t* bufferAddress = context->currentBufferAddress;
|
||||
|
||||
Silkworm_Color color;
|
||||
color.r = 255;
|
||||
color.g = 255;
|
||||
color.b = 255;
|
||||
color.a = 255;
|
||||
|
||||
vertexCount = 0;
|
||||
|
||||
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_Vector2 forwardDirection;
|
||||
forwardDirection.x = nodeTwo->position.x - nodeOne->position.x;
|
||||
forwardDirection.y = nodeTwo->position.y - nodeOne->position.y;
|
||||
|
||||
float forwardLength = sqrtf(forwardDirection.x * forwardDirection.x + forwardDirection.y * forwardDirection.y);
|
||||
|
||||
forwardDirection = Vector2_Normalize(forwardDirection);
|
||||
|
||||
Silkworm_Vector2 upDirection = Vector2_Rotate(forwardDirection, PI / 2);
|
||||
|
||||
Silkworm_Vector2 topLeft;
|
||||
topLeft.x = nodeOne->position.x + upDirection.x * width / 2;
|
||||
topLeft.y = nodeOne->position.y + upDirection.y * width / 2;
|
||||
|
||||
Silkworm_Vector2 bottomLeft;
|
||||
bottomLeft.x = nodeOne->position.x - upDirection.x * width / 2;
|
||||
bottomLeft.y = nodeOne->position.y - upDirection.y * width / 2;
|
||||
|
||||
Silkworm_Vector2 topRight;
|
||||
topRight.x = topLeft.x + forwardDirection.x * forwardLength;
|
||||
topRight.y = topLeft.y + forwardDirection.y * forwardLength;
|
||||
|
||||
Silkworm_Vector2 bottomRight;
|
||||
bottomRight.x = bottomLeft.x + forwardDirection.x * forwardLength;
|
||||
bottomRight.y = bottomLeft.y + forwardDirection.y * forwardLength;
|
||||
|
||||
float uvLeft = (float)leftUV;
|
||||
float uvRight = (float)leftUV + (float)widthUV;
|
||||
|
||||
float uvTop = (float)topUV;
|
||||
float uvBottom = (float)topUV + (float)heightUV;
|
||||
|
||||
/* top left triangle */
|
||||
memcpy(bufferAddress, &topLeft, sizeof(Silkworm_Vector2));
|
||||
bufferAddress += sizeof(Silkworm_Vector2);
|
||||
|
||||
memcpy(bufferAddress, &color, sizeof(Silkworm_Color));
|
||||
bufferAddress += sizeof(Silkworm_Color);
|
||||
|
||||
memcpy(bufferAddress, &uvLeft, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &uvTop, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &topRight, sizeof(Silkworm_Vector2));
|
||||
bufferAddress += sizeof(Silkworm_Vector2);
|
||||
|
||||
memcpy(bufferAddress, &color, sizeof(Silkworm_Color));
|
||||
bufferAddress += sizeof(Silkworm_Color);
|
||||
|
||||
memcpy(bufferAddress, &uvRight, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &uvTop, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &bottomLeft, sizeof(Silkworm_Vector2));
|
||||
bufferAddress += sizeof(Silkworm_Vector2);
|
||||
|
||||
memcpy(bufferAddress, &color, sizeof(Silkworm_Color));
|
||||
bufferAddress += sizeof(Silkworm_Color);
|
||||
|
||||
memcpy(bufferAddress, &uvLeft, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &uvBottom, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
/* bottom right triangle */
|
||||
memcpy(bufferAddress, &bottomLeft, sizeof(Silkworm_Vector2));
|
||||
bufferAddress += sizeof(Silkworm_Vector2);
|
||||
|
||||
memcpy(bufferAddress, &color, sizeof(Silkworm_Color));
|
||||
bufferAddress += sizeof(Silkworm_Color);
|
||||
|
||||
memcpy(bufferAddress, &uvLeft, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &uvBottom, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &topRight, sizeof(Silkworm_Vector2));
|
||||
bufferAddress += sizeof(Silkworm_Vector2);
|
||||
|
||||
memcpy(bufferAddress, &color, sizeof(Silkworm_Color));
|
||||
bufferAddress += sizeof(Silkworm_Color);
|
||||
|
||||
memcpy(bufferAddress, &uvRight, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &uvTop, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &bottomRight, sizeof(Silkworm_Vector2));
|
||||
bufferAddress += sizeof(Silkworm_Vector2);
|
||||
|
||||
memcpy(bufferAddress, &color, sizeof(Silkworm_Color));
|
||||
bufferAddress += sizeof(Silkworm_Color);
|
||||
|
||||
memcpy(bufferAddress, &uvRight, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &uvBottom, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
vertexCount += 6;
|
||||
}
|
||||
|
||||
return (double)vertexCount;
|
||||
}
|
||||
|
||||
/* in bytes */
|
||||
double Silkworm_GetEditorBufferRequiredSize()
|
||||
{
|
||||
|
@ -1404,8 +1676,8 @@ void Silkworm_PushNodesInRadius(double x, double y, double radius, double xDirec
|
|||
|
||||
if (squareDistance <= radius * radius)
|
||||
{
|
||||
node->position.x += (float)xDirection;
|
||||
node->position.y += (float)yDirection;
|
||||
node->position.x += (float)xDirection * node->pushFactor;
|
||||
node->position.y += (float)yDirection * node->pushFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1597,6 +1869,14 @@ void Silkworm_ClearAll()
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < context->ropeCount; i += 1)
|
||||
{
|
||||
if (context->ropes[i] != NULL)
|
||||
{
|
||||
Silkworm_RopeDestroy((double)i);
|
||||
}
|
||||
}
|
||||
|
||||
Silkworm_PerformDestroys();
|
||||
}
|
||||
|
||||
|
@ -1607,10 +1887,12 @@ void Silkworm_Finish()
|
|||
free(context->nodes);
|
||||
free(context->links);
|
||||
free(context->cloths);
|
||||
free(context->ropes);
|
||||
|
||||
free(context->nodeIndexStack);
|
||||
free(context->linkIndexStack);
|
||||
free(context->clothIndexStack);
|
||||
free(context->ropeIndexStack);
|
||||
|
||||
free(context->nodeDestructionData);
|
||||
free(context->linkDestructionData);
|
||||
|
|
|
@ -79,6 +79,12 @@ SILKWORMAPI void Silkworm_DestroyCloth(double clothId);
|
|||
|
||||
SILKWORMAPI double Silkworm_ClothFillTriangleBuffer(double clothId, double leftUV, double widthUV, double topUV, double heightUV);
|
||||
|
||||
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 void Silkworm_RopeDestroy(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_GetEditorBufferRequiredSize();
|
||||
SILKWORMAPI double Silkworm_FillEditorBuffer();
|
||||
|
||||
|
|
Loading…
Reference in New Issue