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