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; | ||||
| 				 | ||||
| 				double translateX = diffX * 0.5 * difference; | ||||
| 				double translateY = diffY * 0.5 * difference; | ||||
| 				float distanceMoved = (float)sqrt(translateX * translateX + translateY * translateY); | ||||
| 
 | ||||
| 				double distanceMoved = sqrt(translateX * translateX + translateY * translateY); | ||||
| 				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; | ||||
| 					} | ||||
| 
 | ||||
| 					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