All pastes #468722 Raw Edit

Miscellany

public text v1 · immutable
·published 2007-05-03 09:45 UTC
rendered paste body
#include "model.h"
#include <malloc.h>
#include <math.h>
#include <GL/gl.h>	// Header File For The OpenGL32 Library

/************************ INITIALIZATION ************************/

void initObject(Object* object, Point3D position);
void initSpring(Spring* spring, Object* a, Object* b);

Model* initModel()
{
	Model* model = (Model*) malloc(sizeof(Model));
	Point3D position;

	int i, j, k = 0;
	
	for (i = 0; i < GRID_WIDTH; i++)
	{
		for (j = 0; j < GRID_HEIGHT; j++)
		{
			position.x = 2 * i * POSITION_RANGE / (GRID_WIDTH - 1) - POSITION_RANGE;
			position.y = 2 * j * POSITION_RANGE / (GRID_HEIGHT - 1) - POSITION_RANGE;
			position.z = 0.0f;
		
			initObject(&model->object[i][j], position);
			
			if (j - 1 >= 0)
			{
				initSpring(&model->spring[k], &model->object[i][j - 1], &model->object[i][j]);
				k++;
			}
			
			if (i - 1 >= 0)
			{
				initSpring(&model->spring[k], &model->object[i - 1][j], &model->object[i][j]);
				k++;
			}
		}
	}
	
	initAnimation(model);
	
	return model;
}

void initObject(Object* object, Point3D position)
{
	object->position = object->prevPosition = position;
	object->anchor = FALSE;
}

void initSpring(Spring* spring, Object* a, Object* b)
{
	spring->a = a;
	spring->b = b;
	
	spring->offset.x = b->position.x - a->position.x;
	spring->offset.y = b->position.y - a->position.y;
	spring->offset.z = b->position.z - a->position.z;
}

/************************ STEPPING ************************/

void cleanForces(Model* model);
void applySpringForce(Spring* spring);
void stepObject(Object* object);

void stepModel(Model* model)
{
	int i, j;
	
	cleanForces(model);
	
	for (i = 0; i < NUM_SPRINGS; i++)
		applySpringForce(&model->spring[i]);
	
	for (i = 0; i < GRID_WIDTH; i++)
	{
		for (j = 0; j < GRID_HEIGHT; j++)
			stepObject(&model->object[i][j]);
	}
	
	stepAnimation(model);
}

void cleanForces(Model* model)
{
	int i, j;
	
	for (i = 0; i < GRID_WIDTH; i++)
	{
		for (j = 0; j < GRID_HEIGHT; j++)
		{
			model->object[i][j].force.x = 0.0f;
			model->object[i][j].force.y = 0.0f;
			model->object[i][j].force.z = 0.0f;
		}
	}
}

void applySpringForce(Spring* spring)
{
	/* TODO: spring_k, double force when the other object is anchor.
	
		 another spring model: the spring can change it's dx / dy / dz as long
		 as the spring's length doesn't change. the spring will act according to
		 the spring length and not according to dx / dy / dz.
	*/
	
	Object* a = spring->a;
	Object* b = spring->b;
	
	Vector3D force;

	force.x = b->position.x - a->position.x - spring->offset.x;
	force.y = b->position.y - a->position.y - spring->offset.y;
	force.z = b->position.z - a->position.z - spring->offset.z;
	
	force.x *= SPRING_K / 40.0f;
	force.y *= SPRING_K / 40.0f;
	force.z *= SPRING_K / 40.0f;
	
	a->force.x += force.x / 2.0f;
	a->force.y += force.y / 2.0f;
	a->force.z += force.z / 2.0f;
	
	b->force.x -= force.x / 2.0f;
	b->force.y -= force.y / 2.0f;
	b->force.z -= force.z / 2.0f;
}

void stepObject(Object* object)
{
	/* TODO: friction, dt (for now it is considered 1. we will need to do position = 2 * position - prevPosition + force * (dt ^ 2))
	*/
	
	if (!object->anchor)
	{
		Vector3D velocity;
		
		velocity.x = object->position.x - object->prevPosition.x;
		velocity.y = object->position.y - object->prevPosition.y;
		velocity.z = object->position.z - object->prevPosition.z;
		
		object->force.x -= FRICTION * velocity.x / 30.0f;
		object->force.y -= FRICTION * velocity.y / 30.0f;
		object->force.z -= FRICTION * velocity.z / 30.0f;
		
		object->prevPosition = object->position;
		
		object->position.x += velocity.x + object->force.x;
		object->position.y += velocity.y + object->force.y;
		object->position.z += velocity.z + object->force.z;
	}
	
	else
	{
		object->prevPosition = object->position;
	}
}

/************************ DRAWING ************************/

Point3D bezierEvaluate(Model* model, float u, float v);
void scalePoint(Point3D* point);

void drawModel(Model* model)
{
	int i, j;
	float u1, u2, v1, v2;
	Point3D vertex1, vertex2, vertex3, vertex4;
	
	glBegin(GL_QUADS);

	for (i = 0; i < PAINT_GRID_WIDTH - 1; i++)
	{
		for (j = 0; j < PAINT_GRID_HEIGHT - 1; j++)
		{
			u1 = (float) i       / (PAINT_GRID_WIDTH - 1);
			u2 = (float) (i + 1) / (PAINT_GRID_WIDTH - 1);
			
			v1 = (float) j       / (PAINT_GRID_HEIGHT - 1);
			v2 = (float) (j + 1) / (PAINT_GRID_HEIGHT - 1);
			
			vertex1 = bezierEvaluate(model, u1, v1);
			vertex2 = bezierEvaluate(model, u1, v2);
			vertex3 = bezierEvaluate(model, u2, v2);
			vertex4 = bezierEvaluate(model, u2, v1);
			
			scalePoint(&vertex1);
			scalePoint(&vertex2);
			scalePoint(&vertex3);
			scalePoint(&vertex4);
			
			glTexCoord2f(u1, v1); glVertex3f(vertex1.x, vertex1.y, vertex1.z);
			glTexCoord2f(u1, v2); glVertex3f(vertex2.x, vertex2.y, vertex2.z);
			glTexCoord2f(u2, v2); glVertex3f(vertex3.x, vertex3.y, vertex3.z);
			glTexCoord2f(u2, v1); glVertex3f(vertex4.x, vertex4.y, vertex4.z);
		}
	}
	
	glEnd();
}

Point3D bezierEvaluate(Model* model, float u, float v)
{
	float coeffsU[GRID_WIDTH], coeffsV[GRID_HEIGHT];
	int   i, j;
	
	Point3D point;
	
	if (u != 1.0f)
	{
		coeffsU[0] = pow(1 - u, GRID_WIDTH - 1);
		for (i = 1; i < GRID_WIDTH; i++)
		{
			coeffsU[i] = coeffsU[i - 1] * u / (1 - u);
			coeffsU[i] *= (float)(GRID_WIDTH - i) / i;
		}
	}
	else
	{
		for (i = 0; i < GRID_WIDTH - 1; i++)
			coeffsU[i] = 0.0f;
		coeffsU[i] = 1.0f;
	}

	if (v != 1.0f)
	{
		coeffsV[0] = pow(1 - v, GRID_HEIGHT - 1);
		for (j = 1; j < GRID_HEIGHT; j++)
		{
			coeffsV[j] = coeffsV[j - 1] * v / (1 - v);
			coeffsV[j] *= (float)(GRID_HEIGHT - j) / j;
		}
	}
	else
	{
		for (j = 0; j < GRID_HEIGHT - 1; j++)
			coeffsV[j] = 0.0f;
		coeffsV[j] = 1.0f;
	}

	point.x = point.y = point.z = 0.0f;

	for (i = 0; i < GRID_WIDTH; i++)
	{
		for (j = 0; j < GRID_HEIGHT; j++)
		{
			point.x += coeffsU[i] * coeffsV[j] * model->object[i][j].position.x;
			point.y += coeffsU[i] * coeffsV[j] * model->object[i][j].position.y;
			point.z += coeffsU[i] * coeffsV[j] * model->object[i][j].position.z;
		}
	}

	return point;
}

void scalePoint(Point3D* point)
{
	point->x *= PAINT_POSITION_RANGE_X / POSITION_RANGE;
	point->y *= PAINT_POSITION_RANGE_Y / POSITION_RANGE;
	point->z *= PAINT_POSITION_RANGE_Z / POSITION_RANGE;
}