view trunk/chipmunkd/chipmunk.d @ 23:4ceef5833c8c

updated to chipmunk 5.3.3
author Extrawurst
date Fri, 10 Dec 2010 02:10:27 +0100
parents df4ebc8add66
children
line wrap: on
line source


// written in the D programming language

module chipmunkd.chipmunk;

import std.stdio;
import std.string:format;
import std.conv:to;
import std.math:PI;

void
cpMessage(string message, string condition, string file, int line, bool isError)
{
	stderr.writeln(.format("%s:%s", isError ? "Aborting due to Chipmunk error" : "Chipmunk warning", message));
	stderr.writeln(.format("\tFailed condition: %s", condition));
	stderr.writeln(.format("\tSource: %s(%s)", file, line));
	
	if(isError) {debug{assert(false);}else{asm{int 3;}}}
}

debug
{
	template cpAssertWarn(string _condition, string message,string _f = __FILE__,int _l=__LINE__)
	{
		enum cpAssertWarn = "if(!("~_condition~"))"~
			"cpMessage(\""~message~"\",\""~_condition~"\",r\""~_f~"\","~to!string(_l)~",false);";
	}
}
else
{
	template cpAssertWarn(string _condition, string message,string _f = __FILE__,int _l=__LINE__)
	{
		enum cpAssertWarn = "";
	}
}

//TODO
//#ifdef NDEBUG
//	#define	cpAssert(condition, message)
//#else
//	#define cpAssert(condition, message) if(!(condition)) cpMessage(message, #condition, __FILE__, __LINE__, 1)
//#endif
//

import chipmunkd.chipmunk_types;
import core.stdc.stdlib;

enum INFINITY = cpFloat.infinity;

// Maximum allocated size for various Chipmunk buffer sizes
enum CP_BUFFER_BYTES = (32*1024);

alias core.stdc.stdlib.malloc cpmalloc;
alias core.stdc.stdlib.calloc cpcalloc;
alias core.stdc.stdlib.realloc cprealloc;
alias core.stdc.stdlib.free cpfree;

public import chipmunkd.cpVect;
public import chipmunkd.cpBB;
public import chipmunkd.cpArray;
public import chipmunkd.cpHashSet;
public import chipmunkd.cpSpaceHash;
//
public import chipmunkd.cpBody;
public import chipmunkd.cpShape;
public import chipmunkd.cpPolyShape;
//
public import chipmunkd.cpArbiter;
public import chipmunkd.cpCollision;
//	
public import chipmunkd.constraints.cpConstraint;
//
public import chipmunkd.cpSpace;
public import chipmunkd.cpSpaceComponent;
public import chipmunkd.cpSpaceQuery;
public import chipmunkd.cpSpaceStep;

public import chipmunkd.chipmunk_types;

enum cpHashValue CP_HASH_COEF = cast(cpHashValue)(3344921057uL); // ulong to uint ??
static cpHashValue CP_HASH_PAIR(T)(T A, T B) {return (cast(cpHashValue)(A)*CP_HASH_COEF ^ cast(cpHashValue)(B)*CP_HASH_COEF);}

extern const char *cpVersionString;
void cpInitChipmunk()
{
	cpInitCollisionFuncs();
}

/**
	Calculate the moment of inertia for a circle.
	r1 and r2 are the inner and outer diameters. A solid circle has an inner diameter of 0.
*/
cpFloat
cpMomentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cpVect offset)
{
	return m*(0.5f*(r1*r1 + r2*r2) + cpvlengthsq(offset));
}

/**
	Calculate area of a hollow circle.
*/
cpFloat cpAreaForCircle(cpFloat r1, cpFloat r2)
{
	return 2.0f*cast(cpFloat)PI*cpfabs(r1*r1 - r2*r2);
}

/**
	Calculate the moment of inertia for a line segment.
	Beveling radius is not supported.
*/
cpFloat
cpMomentForSegment(cpFloat m, cpVect a, cpVect b)
{
	cpFloat length = cpvlength(cpvsub(b, a));
	cpVect offset = cpvmult(cpvadd(a, b), 1.0f/2.0f);
	
	return m*(length*length/12.0f + cpvlengthsq(offset));
}

/**
	Calculate the area of a fattened (capsule shaped) line segment.
*/
cpFloat
cpAreaForSegment(cpVect a, cpVect b, cpFloat r)
{
	return 2.0f*r*(cast(cpFloat)PI*r + cpvdist(a, b));
}

/**
	Calculate the moment of inertia for a solid polygon shape.
*/
cpFloat
cpMomentForPoly(cpFloat m, const int numVerts, cpVect *verts, cpVect offset)
{
	cpVect *tVerts = cast(cpVect *)cpcalloc(numVerts, cpVect.sizeof);
	for(int i=0; i<numVerts; i++)
		tVerts[i] = cpvadd(verts[i], offset);
	
	cpFloat sum1 = 0.0f;
	cpFloat sum2 = 0.0f;
	for(int i=0; i<numVerts; i++){
		cpVect v1 = tVerts[i];
		cpVect v2 = tVerts[(i+1)%numVerts];
		
		cpFloat a = cpvcross(v2, v1);
		cpFloat b = cpvdot(v1, v1) + cpvdot(v1, v2) + cpvdot(v2, v2);
		
		sum1 += a*b;
		sum2 += a;
	}
	
	cpfree(tVerts);
	return (m*sum1)/(6.0f*sum2);
}

/**
	Calculate the signed area of a polygon.
*/
cpFloat cpAreaForPoly(const int numVerts, const cpVect *verts)
{
	cpFloat area = 0.0f;
	for(int i=0; i<numVerts; i++){
		area += cpvcross(verts[i], verts[(i+1)%numVerts]);
	}
	
	return area/2.0f;
}
	
/**
	Calculate the natural centroid of a polygon.
*/
cpVect cpCentroidForPoly(const int numVerts, const cpVect *verts)
{
	cpFloat sum = 0.0f;
	cpVect vsum = cpvzero;
	
	for(int i=0; i<numVerts; i++){
		cpVect v1 = verts[i];
		cpVect v2 = verts[(i+1)%numVerts];
		cpFloat cross = cpvcross(v1, v2);
		
		sum += cross;
		vsum = cpvadd(vsum, cpvmult(cpvadd(v1, v2), cross));
	}
	
	return cpvmult(vsum, 1.0f/(3.0f*sum));
}

/**
	Center the polygon on the origin. (Subtracts the centroid of the polygon from each vertex)
*/
void cpRecenterPoly(const int numVerts, cpVect *verts)
{
	cpVect centroid = cpCentroidForPoly(numVerts, verts);
	
	for(int i=0; i<numVerts; i++){
		verts[i] = cpvsub(verts[i], centroid);
	}
}

/**
	Calculate the moment of inertia for a solid box.
*/
cpFloat
cpMomentForBox(cpFloat m, cpFloat width, cpFloat height)
{
	return m*(width*width + height*height)/12.0f;
}