implement most of the library!
parent
9c522e8447
commit
40b3a6596d
|
@ -0,0 +1,2 @@
|
|||
visualc/.vs
|
||||
visualc/x64
|
548
src/Silkworm.c
548
src/Silkworm.c
|
@ -27,11 +27,45 @@
|
|||
#include "Silkworm.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct Silkworm_Color
|
||||
{
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
uint8_t a;
|
||||
} Silkworm_Color;
|
||||
|
||||
typedef struct Silkworm_Context
|
||||
{
|
||||
Silkworm_Group **groups;
|
||||
uint32_t groupCount;
|
||||
Silkworm_Node** nodes;
|
||||
uint32_t nodeCount;
|
||||
|
||||
Silkworm_Link** links;
|
||||
uint32_t linkCount;
|
||||
|
||||
Silkworm_Cloth** cloths;
|
||||
uint32_t clothCount;
|
||||
|
||||
uint64_t* nodeIndicesToDestroy;
|
||||
uint32_t nodeIndicesToDestroyCount;
|
||||
|
||||
uint64_t* linkIndicesToDestroy;
|
||||
uint32_t linkIndicesToDestroyCount;
|
||||
|
||||
uint64_t* nodeIndexStack;
|
||||
uint32_t nodeIndexStackCount;
|
||||
|
||||
uint64_t* linkIndexStack;
|
||||
uint32_t linkIndexStackCount;
|
||||
|
||||
float gravity;
|
||||
float xBound;
|
||||
float yBound;
|
||||
uint32_t clothDensity;
|
||||
|
||||
uint8_t* currentBufferAddress; /* GM doesnt let you pass more than 4 arguments with different types lol */
|
||||
} Silkworm_Context;
|
||||
|
||||
static Silkworm_Context *context = NULL;
|
||||
|
@ -42,155 +76,485 @@ void Silkworm_Init()
|
|||
{
|
||||
context = malloc(sizeof(Silkworm_Context));
|
||||
|
||||
context->groups = NULL;
|
||||
context->groupCount = 0;
|
||||
context->nodes = NULL;
|
||||
context->nodeCount = 0;
|
||||
context->links = NULL;
|
||||
context->linkCount = 0;
|
||||
|
||||
context->nodeIndicesToDestroy = NULL;
|
||||
context->nodeIndicesToDestroyCount = 0;
|
||||
|
||||
context->linkIndicesToDestroy = NULL;
|
||||
context->linkIndicesToDestroyCount = 0;
|
||||
|
||||
context->nodeIndexStack = NULL;
|
||||
context->nodeIndexStackCount = 0;
|
||||
|
||||
context->linkIndexStack = NULL;
|
||||
context->linkIndexStackCount = 0;
|
||||
|
||||
context->cloths = NULL;
|
||||
context->clothCount = 0;
|
||||
|
||||
context->gravity = 200;
|
||||
context->xBound = 1000;
|
||||
context->yBound = 1000;
|
||||
context->clothDensity = 4;
|
||||
}
|
||||
|
||||
void Silkworm_Update()
|
||||
void Silkworm_Update(double deltaTime)
|
||||
{
|
||||
int32_t i, j, iteration;
|
||||
Silkworm_Group *group;
|
||||
uint32_t i, j;
|
||||
Silkworm_Link *link;
|
||||
Silkworm_Node *node;
|
||||
|
||||
for (iteration = 0; iteration < CONSTRAINT_ITERATION_COUNT; iteration += 1)
|
||||
float delta = (float)deltaTime;
|
||||
|
||||
for (i = 0; i < CONSTRAINT_ITERATION_COUNT; i += 1)
|
||||
{
|
||||
for (i = 0; i < context->groupCount; i += 1)
|
||||
for (j = 0; j < context->linkCount; j += 1)
|
||||
{
|
||||
group = context->groups[i];
|
||||
link = context->links[j];
|
||||
|
||||
for (j = 0; j < group->linkCount; j += 1)
|
||||
if (link != NULL)
|
||||
{
|
||||
link = group->links[j];
|
||||
float diffX = link->a->position.x - link->b->position.x;
|
||||
float diffY = link->a->position.y - link->b->position.y;
|
||||
float d = (float)sqrt(diffX * diffX + diffY * diffY);
|
||||
|
||||
double diffX = link->a->position.x - link->b->position.y;
|
||||
double diffY = link->a->position.y - link->b->position.y;
|
||||
double d = sqrt(diffX * diffX + diffY * diffY);
|
||||
float difference = (link->distance - d) / d;
|
||||
|
||||
double difference = (link->distance - d) / d;
|
||||
float translateX = diffX * 0.5f * difference;
|
||||
float translateY = diffY * 0.5f * difference;
|
||||
|
||||
float distanceMoved = (float)sqrt(translateX * translateX + translateY * translateY);
|
||||
|
||||
double translateX = diffX * 0.5 * difference;
|
||||
double translateY = diffY * 0.5 * difference;
|
||||
if (distanceMoved > link->tearThreshold)
|
||||
{
|
||||
context->linkIndicesToDestroy = realloc(context->linkIndicesToDestroy, sizeof(uint64_t) * (context->linkIndicesToDestroyCount + 1));
|
||||
context->linkIndicesToDestroy[context->linkIndicesToDestroyCount] = link->id;
|
||||
context->linkIndicesToDestroyCount += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!link->a->pinned)
|
||||
{
|
||||
link->a->position.x += translateX;
|
||||
link->a->position.y += translateY;
|
||||
}
|
||||
|
||||
double distanceMoved = sqrt(translateX * translateX + translateY * translateY);
|
||||
if (!link->b->pinned)
|
||||
{
|
||||
link->b->position.x -= translateX;
|
||||
link->b->position.y -= translateY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (j = 0; j < context->nodeCount; j += 1)
|
||||
{
|
||||
node = context->nodes[j];
|
||||
|
||||
if (node != NULL)
|
||||
{
|
||||
if (!node->pinned)
|
||||
{
|
||||
float velocityX = (node->position.x - node->previousPosition.x) * node->friction;
|
||||
float velocityY = (node->position.y - node->previousPosition.y) * node->friction;
|
||||
|
||||
float accelerationX = node->acceleration.x * delta * delta;
|
||||
float accelerationY = (node->acceleration.y + node->mass * context->gravity) * delta * delta;
|
||||
|
||||
node->previousPosition.x = node->position.x;
|
||||
node->previousPosition.y = node->position.y;
|
||||
|
||||
node->position.x += velocityX + accelerationX;
|
||||
node->position.y += velocityY + accelerationY;
|
||||
|
||||
node->velocity.x = velocityX * delta;
|
||||
node->velocity.y = velocityY * delta;
|
||||
|
||||
if (fabs(node->position.x) > context->xBound || fabs(node->position.x) > context->yBound)
|
||||
{
|
||||
context->nodeIndicesToDestroy = realloc(context->nodeIndicesToDestroy, sizeof(uint64_t) * (context->nodeIndicesToDestroyCount + 1));
|
||||
context->nodeIndicesToDestroy[context->nodeIndicesToDestroyCount] = node->id;
|
||||
context->nodeIndicesToDestroyCount += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < context->nodeIndicesToDestroyCount; j += 1)
|
||||
{
|
||||
uint64_t nodeIndex = context->nodeIndicesToDestroy[j];
|
||||
|
||||
free(context->nodes[nodeIndex]);
|
||||
context->nodes[nodeIndex] = NULL;
|
||||
|
||||
context->nodeIndexStack = realloc(context->nodeIndexStack, sizeof(uint64_t) * (context->nodeIndexStackCount + 1));
|
||||
context->nodeIndexStack[context->nodeIndexStackCount] = nodeIndex;
|
||||
context->nodeIndexStackCount += 1;
|
||||
}
|
||||
|
||||
for (j = 0; j < context->linkIndicesToDestroyCount; j += 1)
|
||||
{
|
||||
uint64_t linkIndex = context->linkIndicesToDestroy[j];
|
||||
|
||||
free(context->links[linkIndex]);
|
||||
context->links[linkIndex] = NULL;
|
||||
|
||||
context->linkIndexStack = realloc(context->linkIndexStack, sizeof(uint64_t) * (context->linkIndexStackCount + 1));
|
||||
context->linkIndexStack[context->linkIndexStackCount] = linkIndex;
|
||||
context->linkIndexStackCount += 1;
|
||||
}
|
||||
|
||||
context->nodeIndicesToDestroyCount = 0;
|
||||
context->linkIndicesToDestroyCount = 0;
|
||||
}
|
||||
|
||||
double Silkworm_CreateGroup()
|
||||
static inline Silkworm_Node* LookupNode(double nodeId)
|
||||
{
|
||||
context->groups = realloc(context->groups, sizeof(Silkworm_Group*) * (context->groupCount + 1));
|
||||
|
||||
Silkworm_Group* group = malloc(sizeof(Silkworm_Group));
|
||||
|
||||
group->nodes = NULL;
|
||||
group->nodeCount = 0;
|
||||
group->links = NULL;
|
||||
group->linkCount = 0;
|
||||
|
||||
context->groups[context->groupCount] = group;
|
||||
context->groupCount += 1;
|
||||
|
||||
group->id.i = context->groupCount;
|
||||
|
||||
return group->id.d;
|
||||
return context->nodes[(uint64_t)nodeId];
|
||||
}
|
||||
|
||||
static inline Silkworm_Group* LookupGroup(double groupId)
|
||||
static inline Silkworm_Cloth* LookupCloth(double clothId)
|
||||
{
|
||||
Silkworm_ID gId;
|
||||
gId.d = groupId;
|
||||
|
||||
return context->groups[gId.i];
|
||||
return context->cloths[(uint64_t)clothId];
|
||||
}
|
||||
|
||||
static inline Silkworm_Node* LookupNode(double groupId, double nodeId)
|
||||
double Silkworm_CreateNode(double xPosition, double yPosition, double mass, double friction, double radius, double pushFactor)
|
||||
{
|
||||
Silkworm_ID nId;
|
||||
nId.d = nodeId;
|
||||
Silkworm_Node* node = malloc(sizeof(Silkworm_Node));
|
||||
uint64_t id;
|
||||
|
||||
return LookupGroup(groupId)->nodes[nId.i];
|
||||
}
|
||||
if (context->nodeIndexStackCount > 0)
|
||||
{
|
||||
id = context->nodeIndexStack[context->nodeIndexStackCount - 1];
|
||||
context->nodeIndexStack = realloc(context->nodeIndexStack, sizeof(uint64_t) * (context->nodeIndexStackCount - 1));
|
||||
context->nodeIndexStackCount -= 1;
|
||||
|
||||
double Silkworm_CreateNode(double groupId, double xPosition, double yPosition, double mass, double friction, double radius, double pushFactor)
|
||||
{
|
||||
Silkworm_Group *group = LookupGroup(groupId);
|
||||
context->nodes[id] = node;
|
||||
}
|
||||
else
|
||||
{
|
||||
id = context->nodeCount;
|
||||
|
||||
Silkworm_ID nodeId;
|
||||
nodeId.i = group->nodeCount;
|
||||
context->nodes = realloc(context->nodes, sizeof(Silkworm_Node*) * (context->nodeCount + 1));
|
||||
context->nodes[context->nodeCount] = node;
|
||||
context->nodeCount += 1;
|
||||
}
|
||||
|
||||
Silkworm_Node *node = malloc(sizeof(Silkworm_Node));
|
||||
node->id = nodeId;
|
||||
node->position.x = xPosition;
|
||||
node->position.y = yPosition;
|
||||
node->previousPosition.x = xPosition;
|
||||
node->previousPosition.y = yPosition;
|
||||
node->id = id;
|
||||
node->position.x = (float)xPosition;
|
||||
node->position.y = (float)yPosition;
|
||||
node->previousPosition.x = (float)xPosition;
|
||||
node->previousPosition.y = (float)yPosition;
|
||||
node->velocity.x = 0;
|
||||
node->velocity.y = 0;
|
||||
node->acceleration.x = 0;
|
||||
node->acceleration.y = 0;
|
||||
node->mass = mass;
|
||||
node->friction = friction;
|
||||
node->radius = radius;
|
||||
node->pushFactor = pushFactor;
|
||||
node->mass = (float)mass;
|
||||
node->friction = (float)friction;
|
||||
node->radius = (float)radius;
|
||||
node->pushFactor = (float)pushFactor;
|
||||
node->pinned = false;
|
||||
node->destroyable = false;
|
||||
|
||||
group->nodes = realloc(group->nodes, sizeof(Silkworm_Node*) * (group->nodeCount + 1));
|
||||
group->nodes[group->nodeCount] = node;
|
||||
group->nodeCount += 1;
|
||||
|
||||
return nodeId.d;
|
||||
return (double)node->id;
|
||||
}
|
||||
|
||||
void Silkworm_NodeSetVelocity(double groupId, double nodeId, double xVelocity, double yVelocity)
|
||||
void Silkworm_NodeSetVelocity(double nodeId, double xVelocity, double yVelocity)
|
||||
{
|
||||
LookupNode(groupId, nodeId)->velocity.x = xVelocity;
|
||||
LookupNode(groupId, nodeId)->velocity.y = yVelocity;
|
||||
LookupNode(nodeId)->velocity.x = (float)xVelocity;
|
||||
LookupNode(nodeId)->velocity.y = (float)yVelocity;
|
||||
}
|
||||
|
||||
void Silkworm_NodeSetAcceleration(double groupId, double nodeId, double xAcceleration, double yAcceleration)
|
||||
void Silkworm_NodeSetAcceleration(double nodeId, double xAcceleration, double yAcceleration)
|
||||
{
|
||||
LookupNode(groupId, nodeId)->acceleration.x = xAcceleration;
|
||||
LookupNode(groupId, nodeId)->acceleration.y = yAcceleration;
|
||||
LookupNode(nodeId)->acceleration.x = (float)xAcceleration;
|
||||
LookupNode(nodeId)->acceleration.y = (float)yAcceleration;
|
||||
}
|
||||
|
||||
void Silkworm_NodeSetDestroyable(double groupId, double nodeId)
|
||||
void Silkworm_NodeSetDestroyable(double nodeId)
|
||||
{
|
||||
LookupNode(groupId, nodeId)->destroyable = true;
|
||||
LookupNode(nodeId)->destroyable = true;
|
||||
}
|
||||
|
||||
void Silkworm_NodePin(double groupId, double nodeId)
|
||||
void Silkworm_NodePin(double nodeId)
|
||||
{
|
||||
LookupNode(groupId, nodeId)->pinned = true;
|
||||
LookupNode(nodeId)->pinned = true;
|
||||
}
|
||||
|
||||
void Silkworm_NodeUnpin(double groupId, double nodeId)
|
||||
void Silkworm_NodeUnpin(double nodeId)
|
||||
{
|
||||
LookupNode(groupId, nodeId)->pinned = false;
|
||||
LookupNode(nodeId)->pinned = false;
|
||||
}
|
||||
|
||||
double Silkworm_CreateLink(double groupId, double aId, double bId, double distance, double tearThreshold)
|
||||
double Silkworm_CreateLink(double aId, double bId, double distance, double tearThreshold)
|
||||
{
|
||||
Silkworm_Group *group = LookupGroup(groupId);
|
||||
Silkworm_Node *nodeA = LookupNode(aId);
|
||||
Silkworm_Node *nodeB = LookupNode(bId);
|
||||
|
||||
Silkworm_Node *nodeA = LookupNode(groupId, aId);
|
||||
Silkworm_Node *nodeB = LookupNode(groupId, bId);
|
||||
uint64_t id;
|
||||
|
||||
Silkworm_ID linkId;
|
||||
linkId.i = group->linkCount;
|
||||
Silkworm_Link* link = malloc(sizeof(Silkworm_Link));
|
||||
|
||||
Silkworm_Link *link = malloc(sizeof(Silkworm_Link));
|
||||
link->id = linkId;
|
||||
if (context->linkIndexStackCount > 0)
|
||||
{
|
||||
id = context->linkIndexStack[context->linkIndexStackCount - 1];
|
||||
context->linkIndexStack = realloc(context->linkIndexStack, sizeof(uint64_t) * (context->linkIndexStackCount - 1));
|
||||
context->linkIndexStackCount -= 1;
|
||||
|
||||
context->links[id] = link;
|
||||
}
|
||||
else
|
||||
{
|
||||
id = context->linkCount;
|
||||
|
||||
context->links = realloc(context->links, sizeof(Silkworm_Link*) * (context->linkCount + 1));
|
||||
context->links[context->linkCount] = link;
|
||||
context->linkCount += 1;
|
||||
}
|
||||
|
||||
link->id = id;
|
||||
link->a = nodeA;
|
||||
link->b = nodeB;
|
||||
link->distance = distance;
|
||||
link->tearThreshold = tearThreshold;
|
||||
link->distance = (float)distance;
|
||||
link->tearThreshold = (float)tearThreshold;
|
||||
|
||||
group->links = realloc(group->links, sizeof(Silkworm_Link*) * (group->linkCount + 1));
|
||||
group->links[group->linkCount] = link;
|
||||
group->linkCount += 1;
|
||||
|
||||
return linkId.d;
|
||||
return (double)link->id;
|
||||
}
|
||||
|
||||
double Silkworm_CreateCloth(double xPosition, double yPosition, double horizontalNodeCount, double verticalNodeCount, double mass, double friction, double windFactor, double tearThreshold)
|
||||
{
|
||||
int32_t i, j;
|
||||
|
||||
Silkworm_Cloth* cloth = malloc(sizeof(Silkworm_Cloth));
|
||||
|
||||
cloth->windFactor = (float)windFactor;
|
||||
cloth->horizontalNodeCount = (uint32_t) horizontalNodeCount;
|
||||
cloth->verticalNodeCount = (uint32_t) verticalNodeCount;
|
||||
cloth->nodeIndices = malloc(sizeof(uint64_t*) * cloth->horizontalNodeCount);
|
||||
|
||||
for (i = 0; i < horizontalNodeCount; i += 1)
|
||||
{
|
||||
cloth->nodeIndices[i] = malloc(sizeof(uint64_t) * cloth->verticalNodeCount);
|
||||
|
||||
for (j = 0; j < verticalNodeCount; j += 1)
|
||||
{
|
||||
uint64_t id = (uint64_t) Silkworm_CreateNode(xPosition + i * context->clothDensity, yPosition + j * context->clothDensity, mass, friction, 1, 0.5);
|
||||
|
||||
if (j == 0)
|
||||
{
|
||||
Silkworm_NodePin((double)id);
|
||||
}
|
||||
|
||||
Silkworm_NodeSetDestroyable((double)id);
|
||||
|
||||
cloth->nodeIndices[i][j] = id;
|
||||
}
|
||||
}
|
||||
|
||||
cloth->triangles = malloc(sizeof(Silkworm_Triangle*) * cloth->horizontalNodeCount * cloth->verticalNodeCount * 2);
|
||||
uint32_t triangleIndex = 0;
|
||||
|
||||
for (i = 0; i < horizontalNodeCount; i += 1)
|
||||
{
|
||||
for (j = 0; j < verticalNodeCount; j += 1)
|
||||
{
|
||||
if (i + 1 < horizontalNodeCount && j + 1 < verticalNodeCount)
|
||||
{
|
||||
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]->orientation = UpperLeft;
|
||||
|
||||
cloth->triangles[triangleIndex]->aHorizontalIndex = i;
|
||||
cloth->triangles[triangleIndex]->aVerticalIndex = j;
|
||||
|
||||
cloth->triangles[triangleIndex]->bHorizontalIndex = i + 1;
|
||||
cloth->triangles[triangleIndex]->bVerticalIndex = j;
|
||||
|
||||
cloth->triangles[triangleIndex]->cHorizontalIndex = i;
|
||||
cloth->triangles[triangleIndex]->cVerticalIndex = j + 1;
|
||||
|
||||
triangleIndex += 1;
|
||||
}
|
||||
|
||||
if (i - 1 >= 0 && j - 1 >= 0)
|
||||
{
|
||||
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]->orientation = BottomRight;
|
||||
|
||||
cloth->triangles[triangleIndex]->aHorizontalIndex = i;
|
||||
cloth->triangles[triangleIndex]->aVerticalIndex = j;
|
||||
|
||||
cloth->triangles[triangleIndex]->bHorizontalIndex = i - 1;
|
||||
cloth->triangles[triangleIndex]->bVerticalIndex = j;
|
||||
|
||||
cloth->triangles[triangleIndex]->cHorizontalIndex = i;
|
||||
cloth->triangles[triangleIndex]->cVerticalIndex = j - 1;
|
||||
|
||||
triangleIndex += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cloth->triangleCount = triangleIndex;
|
||||
|
||||
for (i = 0; i < horizontalNodeCount; i += 1)
|
||||
{
|
||||
for (j = 0; j < verticalNodeCount; j += 1)
|
||||
{
|
||||
if (i - 1 >= 0)
|
||||
{
|
||||
Silkworm_CreateLink((double)cloth->nodeIndices[i - 1][j], (double)cloth->nodeIndices[i][j], context->clothDensity, tearThreshold);
|
||||
}
|
||||
|
||||
if (j - 1 >= 0)
|
||||
{
|
||||
Silkworm_CreateLink((double)cloth->nodeIndices[i][j - 1], (double)cloth->nodeIndices[i][j], context->clothDensity, tearThreshold);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t id;
|
||||
id = context->clothCount;
|
||||
|
||||
cloth->id = id;
|
||||
context->cloths = realloc(context->cloths, sizeof(Silkworm_Cloth*) * (context->clothCount + 1));
|
||||
context->cloths[context->clothCount] = cloth;
|
||||
context->clothCount += 1;
|
||||
|
||||
return (double)cloth->id;
|
||||
}
|
||||
|
||||
void Silkworm_SetTriangleBuffer(const char* bufferId)
|
||||
{
|
||||
context->currentBufferAddress = (uint8_t*)bufferId;
|
||||
}
|
||||
|
||||
/* pattern is x, y position then color + alpha then UV position */
|
||||
double Silkworm_ClothFillTriangleBuffer(double clothId, double leftUV, double widthUV, double topUV, double heightUV)
|
||||
{
|
||||
uint32_t i, triangleCount;
|
||||
uint8_t* bufferAddress = context->currentBufferAddress;
|
||||
Silkworm_Cloth* cloth = LookupCloth(clothId);
|
||||
|
||||
Silkworm_Color color;
|
||||
color.r = 255;
|
||||
color.g = 255;
|
||||
color.b = 255;
|
||||
color.a = 255;
|
||||
|
||||
triangleCount = 0;
|
||||
for (i = 0; i < cloth->triangleCount; i += 1)
|
||||
{
|
||||
if (cloth->triangles[i] != NULL)
|
||||
{
|
||||
if (cloth->triangles[i]->orientation == UpperLeft)
|
||||
{
|
||||
float left = (float)leftUV + (float)widthUV * ((float)cloth->triangles[i]->aHorizontalIndex / (cloth->horizontalNodeCount - 1));
|
||||
float right = (float)leftUV + (float)widthUV * ((float)cloth->triangles[i]->bHorizontalIndex / (cloth->horizontalNodeCount - 1));
|
||||
|
||||
float top = (float)topUV + (float)heightUV * ((float)cloth->triangles[i]->aVerticalIndex / (cloth->verticalNodeCount - 1));
|
||||
float bottom = (float)topUV + (float)heightUV * ((float)cloth->triangles[i]->cVerticalIndex / (cloth->verticalNodeCount - 1));
|
||||
|
||||
memcpy(bufferAddress, &cloth->triangles[i]->a->position, sizeof(Silkworm_Vector2));
|
||||
bufferAddress += sizeof(Silkworm_Vector2);
|
||||
|
||||
memcpy(bufferAddress, &color, sizeof(Silkworm_Color));
|
||||
bufferAddress += sizeof(Silkworm_Color);
|
||||
|
||||
memcpy(bufferAddress, &left, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &top, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &cloth->triangles[i]->b->position, sizeof(Silkworm_Vector2));
|
||||
bufferAddress += sizeof(Silkworm_Vector2);
|
||||
|
||||
memcpy(bufferAddress, &color, sizeof(Silkworm_Color));
|
||||
bufferAddress += sizeof(Silkworm_Color);
|
||||
|
||||
memcpy(bufferAddress, &right, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &top, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &cloth->triangles[i]->c->position, sizeof(Silkworm_Vector2));
|
||||
bufferAddress += sizeof(Silkworm_Vector2);
|
||||
|
||||
memcpy(bufferAddress, &color, sizeof(Silkworm_Color));
|
||||
bufferAddress += sizeof(Silkworm_Color);
|
||||
|
||||
memcpy(bufferAddress, &left, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &bottom, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
triangleCount += 1;
|
||||
}
|
||||
else if (cloth->triangles[i]->orientation == BottomRight)
|
||||
{
|
||||
float left = (float)leftUV + (float)widthUV * ((float)cloth->triangles[i]->bHorizontalIndex / (cloth->horizontalNodeCount - 1));
|
||||
float right = (float)leftUV + (float)widthUV * ((float)cloth->triangles[i]->aHorizontalIndex / (cloth->horizontalNodeCount - 1));
|
||||
|
||||
float top = (float)topUV + (float)heightUV * ((float)cloth->triangles[i]->cVerticalIndex / (cloth->verticalNodeCount - 1));
|
||||
float bottom = (float)topUV + (float)heightUV * ((float)cloth->triangles[i]->aVerticalIndex / (cloth->verticalNodeCount - 1));
|
||||
|
||||
memcpy(bufferAddress, &cloth->triangles[i]->a->position, sizeof(Silkworm_Vector2));
|
||||
bufferAddress += sizeof(Silkworm_Vector2);
|
||||
|
||||
memcpy(bufferAddress, &color, sizeof(Silkworm_Color));
|
||||
bufferAddress += sizeof(Silkworm_Color);
|
||||
|
||||
memcpy(bufferAddress, &right, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &bottom, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &cloth->triangles[i]->b->position, sizeof(Silkworm_Vector2));
|
||||
bufferAddress += sizeof(Silkworm_Vector2);
|
||||
|
||||
memcpy(bufferAddress, &color, sizeof(Silkworm_Color));
|
||||
bufferAddress += sizeof(Silkworm_Color);
|
||||
|
||||
memcpy(bufferAddress, &left, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &bottom, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &cloth->triangles[i]->c->position, sizeof(Silkworm_Vector2));
|
||||
bufferAddress += sizeof(Silkworm_Vector2);
|
||||
|
||||
memcpy(bufferAddress, &color, sizeof(Silkworm_Color));
|
||||
bufferAddress += sizeof(Silkworm_Color);
|
||||
|
||||
memcpy(bufferAddress, &right, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
memcpy(bufferAddress, &top, sizeof(float));
|
||||
bufferAddress += sizeof(float);
|
||||
|
||||
triangleCount += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (double)triangleCount;
|
||||
}
|
||||
|
|
|
@ -43,51 +43,80 @@
|
|||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Game Maker only lets us use doubles in the API. So we do type punning to get integers. It's legal in C99! */
|
||||
typedef union {
|
||||
int i;
|
||||
double d;
|
||||
} Silkworm_ID;
|
||||
|
||||
typedef struct Silkworm_Vector2
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
float x;
|
||||
float y;
|
||||
} Silkworm_Vector2;
|
||||
|
||||
typedef struct Silkworm_Node
|
||||
{
|
||||
Silkworm_ID id;
|
||||
uint64_t id;
|
||||
Silkworm_Vector2 position;
|
||||
Silkworm_Vector2 previousPosition;
|
||||
Silkworm_Vector2 velocity;
|
||||
Silkworm_Vector2 acceleration;
|
||||
double mass;
|
||||
double friction;
|
||||
double radius;
|
||||
double pinned;
|
||||
double pushFactor;
|
||||
float mass;
|
||||
float friction;
|
||||
float radius;
|
||||
float pinned;
|
||||
float pushFactor;
|
||||
bool destroyable;
|
||||
} Silkworm_Node;
|
||||
|
||||
typedef struct Silkworm_Link
|
||||
{
|
||||
Silkworm_ID id;
|
||||
uint64_t id;
|
||||
Silkworm_Node *a;
|
||||
Silkworm_Node *b;
|
||||
double distance;
|
||||
double tearThreshold;
|
||||
float distance;
|
||||
float tearThreshold;
|
||||
} Silkworm_Link;
|
||||
|
||||
typedef struct Silkworm_Group
|
||||
typedef enum Silkworm_ClothTriangleOrientation
|
||||
{
|
||||
UpperLeft,
|
||||
BottomRight
|
||||
} Silkworm_ClothTriangleOrientation;
|
||||
|
||||
typedef struct Silkworm_Triangle
|
||||
{
|
||||
uint64_t id;
|
||||
Silkworm_Node* a;
|
||||
Silkworm_Node* b;
|
||||
Silkworm_Node* c;
|
||||
|
||||
uint32_t aHorizontalIndex;
|
||||
uint32_t bHorizontalIndex;
|
||||
uint32_t cHorizontalIndex;
|
||||
|
||||
uint32_t aVerticalIndex;
|
||||
uint32_t bVerticalIndex;
|
||||
uint32_t cVerticalIndex;
|
||||
|
||||
Silkworm_ClothTriangleOrientation orientation;
|
||||
} Silkworm_Triangle;
|
||||
|
||||
typedef struct Silkworm_Cloth
|
||||
{
|
||||
uint64_t id;
|
||||
float windFactor;
|
||||
|
||||
uint32_t horizontalNodeCount;
|
||||
uint32_t verticalNodeCount;
|
||||
|
||||
uint64_t **nodeIndices; /* x by y grid of indices */
|
||||
|
||||
Silkworm_Triangle **triangles; /* array of pointers so we can use NULL */
|
||||
uint32_t triangleCount;
|
||||
} Silkworm_Cloth;
|
||||
|
||||
typedef struct Silkworm_Rope
|
||||
{
|
||||
Silkworm_ID id;
|
||||
Silkworm_Node **nodes;
|
||||
uint32_t nodeCount;
|
||||
|
||||
Silkworm_Link **links;
|
||||
uint32_t linkCount;
|
||||
} Silkworm_Group;
|
||||
uint32_t *nodeIndices;
|
||||
} Silkworm_Rope;
|
||||
|
||||
/* Version API */
|
||||
|
||||
|
@ -103,19 +132,19 @@ typedef struct Silkworm_Group
|
|||
)
|
||||
|
||||
SILKWORMAPI void Silkworm_Init();
|
||||
SILKWORMAPI void Silkworm_Update();
|
||||
SILKWORMAPI void Silkworm_Update(double delta);
|
||||
|
||||
SILKWORMAPI double Silkworm_CreateGroup();
|
||||
SILKWORMAPI double Silkworm_CreateNode(double xPosition, double yPosition, double mass, double friction, double radius, double pushFactor);
|
||||
|
||||
SILKWORMAPI double Silkworm_CreateNode(double groupId, double xPosition, double yPosition, double mass, double friction, double radius, double pushFactor);
|
||||
SILKWORMAPI void Silkworm_NodeSetDestroyable(double nodeId);
|
||||
SILKWORMAPI void Silkworm_NodePin(double nodeId);
|
||||
SILKWORMAPI void Silkworm_NodeUnpin(double nodeId);
|
||||
|
||||
SILKWORMAPI void Silkworm_NodeSetVelocity(double groupId, double nodeId, double xVelocity, double yVelocity);
|
||||
SILKWORMAPI void Silkworm_NodeSetAcceleration(double groupId, double nodeId, double xAcceleration, double yAcceleration);
|
||||
SILKWORMAPI double Silkworm_CreateLink(double aId, double bId, double distance, double tearThreshold);
|
||||
|
||||
SILKWORMAPI void Silkworm_NodeSetDestroyable(double groupId, double nodeId);
|
||||
SILKWORMAPI void Silkworm_NodePin(double groupId, double nodeId);
|
||||
SILKWORMAPI void Silkworm_NodeUnpin(double groupId, double nodeId);
|
||||
SILKWORMAPI double Silkworm_CreateCloth(double xPosition, double yPosition, double horizontalNodeCount, double verticalNodeCount, double mass, double friction, double windFactor, double tearThreshold);
|
||||
|
||||
SILKWORMAPI double Silkworm_CreateLink(double groupId, double aId, double bId, double distance, double tearThreshold);
|
||||
SILKWORMAPI void Silkworm_SetTriangleBuffer(const char* bufferId);
|
||||
SILKWORMAPI double Silkworm_ClothFillTriangleBuffer(double clothId, double leftUV, double widthUV, double topUV, double heightUV);
|
||||
|
||||
#endif /* SILKWORM_H */
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{6DB15344-E000-45CB-A48A-1D72F7D6E945}</ProjectGuid>
|
||||
<RootNamespace>Silkworm</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||
|
@ -36,16 +36,16 @@
|
|||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
|
|
Loading…
Reference in New Issue