summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/GameDraw.cpp4
-rw-r--r--src/GameInitDispose.cpp2
-rw-r--r--src/GameLoop.cpp8
-rw-r--r--src/GameTick.cpp103
-rw-r--r--src/Globals.cpp5
-rw-r--r--src/Models.cpp116
-rw-r--r--src/Models.h6
-rw-r--r--src/Person.cpp69
-rw-r--r--src/Quaternions.cpp54
-rw-r--r--src/Quaternions.h5
-rw-r--r--src/Skeleton.cpp23
-rw-r--r--src/geom.zig22
12 files changed, 160 insertions, 257 deletions
diff --git a/src/GameDraw.cpp b/src/GameDraw.cpp
index 1fbbca2..cdd0229 100644
--- a/src/GameDraw.cpp
+++ b/src/GameDraw.cpp
@@ -682,13 +682,13 @@ void Game::DrawGLScene(void)
 
 			if(person[i].killtarget>-1&&person[i].killtargetvisible&&person[i].skeleton.free==0&&person[person[i].killtarget].skeleton.free==0){
 
-				sprites.MakeSprite(bulletinstant, (shotdelayamount/difficulty-person[i].shotdelay)/shotdelayamount/difficulty/2, 1, person[i].shotdelay/shotdelayamount/difficulty, person[i].shotdelay/shotdelayamount/difficulty, DoRotation(person[i].skeleton.joints[lefthand].position,0,person[i].playerrotation,0)+person[i].playercoords, person[person[i].killtarget].skeleton.joints[abdomen].position+person[person[i].killtarget].playercoords, person[i].shotdelay*2);
+				sprites.MakeSprite(bulletinstant, (shotdelayamount/difficulty-person[i].shotdelay)/shotdelayamount/difficulty/2, 1, person[i].shotdelay/shotdelayamount/difficulty, person[i].shotdelay/shotdelayamount/difficulty, rotate(person[i].skeleton.joints[lefthand].position,0,person[i].playerrotation,0)+person[i].playercoords, person[person[i].killtarget].skeleton.joints[abdomen].position+person[person[i].killtarget].playercoords, person[i].shotdelay*2);
 
 			}
 
 			if(person[i].killtarget>-1&&person[i].killtargetvisible&&person[i].skeleton.free==0&&person[person[i].killtarget].skeleton.free!=0){
 
-				sprites.MakeSprite(bulletinstant, (shotdelayamount/difficulty-person[i].shotdelay)/shotdelayamount/difficulty/2, 1, person[i].shotdelay/shotdelayamount/difficulty, person[i].shotdelay/shotdelayamount/difficulty, DoRotation(person[i].skeleton.joints[lefthand].position,0,person[i].playerrotation,0)+person[i].playercoords, person[person[i].killtarget].skeleton.joints[abdomen].position, person[i].shotdelay*2);
+				sprites.MakeSprite(bulletinstant, (shotdelayamount/difficulty-person[i].shotdelay)/shotdelayamount/difficulty/2, 1, person[i].shotdelay/shotdelayamount/difficulty, person[i].shotdelay/shotdelayamount/difficulty, rotate(person[i].skeleton.joints[lefthand].position,0,person[i].playerrotation,0)+person[i].playercoords, person[person[i].killtarget].skeleton.joints[abdomen].position, person[i].shotdelay*2);
 
 			}
 
diff --git a/src/GameInitDispose.cpp b/src/GameInitDispose.cpp
index d31829b..0a21275 100644
--- a/src/GameInitDispose.cpp
+++ b/src/GameInitDispose.cpp
@@ -242,7 +242,7 @@ void initGame(Game* game)
 		point0.z = boundingscale;
 
 		for (int i = 1; i < 8; ++i)
-			game->boundingpoints[i] = DoRotation(point0,
+			game->boundingpoints[i] = rotate(point0,
 					0, i * 360 / 7, 0);
 	}
 
diff --git a/src/GameLoop.cpp b/src/GameLoop.cpp
index c3eefad..ccf99ac 100644
--- a/src/GameLoop.cpp
+++ b/src/GameLoop.cpp
@@ -171,8 +171,8 @@ void handleKey(Game* game, int key, int action, int mods)
 		alSourcef(gSourceID[shootsong], AL_PITCH, pitch);
 		alSourcef(gSourceID[zombiesong], AL_PITCH, pitch);
 	} else if (key == keymap.force) {
-		auto facing = DoRotation({0, 0, -1}, -camera.rotation2, 0, 0);
-		facing = DoRotation(facing, 0, 0 - camera.rotation, 0);
+		auto facing = rotate({0, 0, -1}, -camera.rotation2, 0, 0);
+		facing = rotate(facing, 0, 0 - camera.rotation, 0);
 		alSourcePlay(gSourceID[souloutsound]);
 
 		for (int i = 1; i < game->numpeople; i++) {
@@ -184,11 +184,11 @@ void handleKey(Game* game, int key, int action, int mods)
 			person.longdead = 1;
 
 			for (auto& joint : person.skeleton.joints) {
-				joint.position = DoRotation(joint.position,
+				joint.position = rotate(joint.position,
 					0, person.playerrotation, 0);
 				joint.position += person.playercoords;
 				joint.realoldposition = joint.position;
-				joint.velocity = DoRotation(joint.velocity,
+				joint.velocity = rotate(joint.velocity,
 					0, person.playerrotation, 0);
 				joint.velocity += person.velocity;
 				joint.velocity += facing * 50;
diff --git a/src/GameTick.cpp b/src/GameTick.cpp
index 3f42796..fa64e6a 100644
--- a/src/GameTick.cpp
+++ b/src/GameTick.cpp
@@ -70,7 +70,7 @@ void Splat(Game* game, int k)
 	person.bjoint2 = joints + neck;
 
 	for (auto& joint : joints) {
-		joint.position = DoRotation(joint.position + joint.offset, 0,
+		joint.position = rotate(joint.position + joint.offset, 0,
 			person.playerrotation, 0) + person.playercoords;
 		joint.realoldposition = joint.position;
 		joint.velocity = {0, person.velocity.y, 0};
@@ -181,8 +181,8 @@ void click(Game* game, int button, int action, int mods)
 	}
 
 	XYZ facing {0, 0, -1};
-	facing = DoRotation(facing, -camera.rotation2, 0, 0);
-	facing = DoRotation(facing, 0, -camera.rotation, 0);
+	facing = rotate(facing, -camera.rotation2, 0, 0);
+	facing = rotate(facing, 0, -camera.rotation, 0);
 
 	XYZ flatfacing = facing;
 	flatfacing.y = 0;
@@ -281,7 +281,7 @@ void click(Game* game, int button, int action, int mods)
 	    && player.reloading <= 0 && player.attackframe < 0) {
 		auto& skeleton = player.skeleton;
 		auto& hand = skeleton.joints[righthand];
-		auto soundsrc = DoRotation(hand.position, 0, player.playerrotation, 0)
+		auto soundsrc = rotate(hand.position, 0, player.playerrotation, 0)
 			+ player.playercoords - camera.position;
 		if (player.grenphase) {
 			if (button == GLFW_MOUSE_BUTTON_LEFT
@@ -354,8 +354,8 @@ void look(Game* game, double xpos, double ypos)
 void setListener(Game* game, XYZ facing)
 {
 	XYZ upvector {0, 0, -1};
-	upvector = DoRotation(upvector, -camera.rotation2 + 90, 0, 0);
-	upvector = DoRotation(upvector, 0, -camera.rotation, 0);
+	upvector = rotate(upvector, -camera.rotation2 + 90, 0, 0);
+	upvector = rotate(upvector, 0, -camera.rotation, 0);
 
 	ALfloat ori[] {
 		facing.x, facing.y, facing.z,
@@ -391,7 +391,7 @@ XYZ aimPlayer(Game* game)
 		break;
 	}
 
-	return DoRotation(point, aimrot2,
+	return rotate(point, aimrot2,
 		game->person[0].playerrotation + aimrot, 0);
 }
 
@@ -422,14 +422,14 @@ XYZ aimBot(Game* game, int j)
 	if (target.skeleton.free)
 		inaccuracy *= 3;
 	else
-		aim = DoRotation(aim, 0, target.playerrotation, 0)
+		aim = rotate(aim, 0, target.playerrotation, 0)
 			+ target.playercoords;
 
 	auto& lefthandpos = joints[lefthand].position;
 	aim -= bot.playercoords
-		+ DoRotation(lefthandpos, 0, bot.playerrotation, 0);
-	return DoRotation(
-		DoRotation(DoRotation(aim, 0, -bot.playerrotation, 0),
+		+ rotate(lefthandpos, 0, bot.playerrotation, 0);
+	return rotate(
+		rotate(rotate(aim, 0, -bot.playerrotation, 0),
 			randFloat() * inaccuracy, randFloat() * inaccuracy, 0),
 		0, bot.playerrotation, 0);
 }
@@ -515,12 +515,11 @@ void checkPersonCollisions(Game* game, int k)
 			game->onblocky = j;
 
 			// Wall collision
-			float depth;
 			const auto city_type = game->citytype[i][j];
 			for (auto& bound : game->boundingpoints) {
-				const auto whichtri = game->blockwalls[city_type].LineCheck3(person.playercoords + bound,
+				const auto whichtri = game->blockwalls[city_type].LineCheck2(person.playercoords + bound,
 					person.playercoords + bound,
-					&collpoint, move, city_rot, &depth);
+					&collpoint, move, city_rot);
 				if (whichtri == -1)
 					continue;
 			}
@@ -528,12 +527,12 @@ void checkPersonCollisions(Game* game, int k)
 				auto pointnum = k + 1;
 				if (pointnum > 3)
 					pointnum = 0;
-				const auto whichtri = game->blockwalls[city_type].LineCheck3(person.playercoords + bound,
+				const auto whichtri = game->blockwalls[city_type].LineCheck2(person.playercoords + bound,
 					person.playercoords + game->boundingpoints[pointnum],
-					&collpoint, move, city_rot, &depth);
+					&collpoint, move, city_rot);
 				if (whichtri == -1)
 					continue;
-				person.playercoords += DoRotation(game->blockwalls[city_type].normals[whichtri], 0, city_rot, 0);
+				person.playercoords += rotate(game->blockwalls[city_type].normals[whichtri], 0, city_rot, 0);
 			}
 		}
 
@@ -662,7 +661,7 @@ void attackCloseRange(Game* game, XYZ flatfacing)
 	}
 
 	for (auto& joint : target.skeleton.joints) {
-		joint.position = DoRotation(joint.position,
+		joint.position = rotate(joint.position,
 			0, target.playerrotation, 0);
 		joint.position += target.playercoords;
 		joint.realoldposition = joint.position;
@@ -687,11 +686,11 @@ void attackCloseRange(Game* game, XYZ flatfacing)
 		player.bleeding=1;
 		player.bleeddelay=1;
 
-		auto velocity = DoRotation(flatfacing, 0, 70, 0) * 50
+		auto velocity = rotate(flatfacing, 0, 70, 0) * 50
 			+ player.velocity * 2;
 		velocity.y += 30;
 		auto sprite_pos = target.playercoords
-			+ DoRotation(target.skeleton.joints[neck].position,
+			+ rotate(target.skeleton.joints[neck].position,
 				0, target.playerrotation, 0);
 		for (auto i = 2; i < 5; ++i)
 			sprites.MakeSprite(bloodspritedown,
@@ -701,7 +700,7 @@ void attackCloseRange(Game* game, XYZ flatfacing)
 		playSound(gSourceID[headwhacksound],
 			soundpos.x, soundpos.y, soundpos.z);
 		target.skeleton.joints[head].velocity
-			+= DoRotation(flatfacing, 0, 40, 0) * 50
+			+= rotate(flatfacing, 0, 40, 0) * 50
 			+ player.velocity * 2;
 	}
 }
@@ -728,7 +727,7 @@ void tackle(Game* game, XYZ flatfacing)
 
 		for (auto& joint : person.skeleton.joints) {
 			joint.position = person.playercoords
-				+ DoRotation(joint.position,
+				+ rotate(joint.position,
 					0, person.playerrotation, 0);
 			joint.realoldposition = joint.position;
 			joint.velocity = player.velocity;
@@ -781,7 +780,7 @@ void bleed(Game* game, size_t i)
 	person.bleeddelay = 1.0f;
 	XYZ loc = (person.bjoint1->position + person.bjoint2->position) / 2.0f;
 	sprites.MakeSprite(bloodspritedown, 0.6f, 1.0f, 0.2f, 0.2f,
-		person.skeleton.free ? loc : DoRotation(loc,
+		person.skeleton.free ? loc : rotate(loc,
 			0.0f, person.playerrotation, 0.0f) + person.playercoords,
 		{}, person.bleeding * 3.0f);
 }
@@ -875,11 +874,11 @@ void controlZombie(Game* game, size_t i)
 
 	auto& zombie_joints = zombie.skeleton.joints;
 	target_joints[head].position = zombie.playercoords
-		+ DoRotation(zombie_joints[righthand].position,
+		+ rotate(zombie_joints[righthand].position,
 			0.0f, zombie.playerrotation, 0.0f);
 	target_joints[head].velocity = {};
 	target_joints[rightshoulder].position = zombie.playercoords
-		+ DoRotation(zombie_joints[lefthand].position,
+		+ rotate(zombie_joints[lefthand].position,
 			0.0f, zombie.playerrotation, 0.0f);
 	target_joints[rightshoulder].velocity = {};
 	target.skeleton.DoConstraints();
@@ -915,14 +914,14 @@ void renderLaser(Game* game)
 	switch (player.whichgun) {
 	case assaultrifle:
 	case shotgun:
-		aim = DoRotation(joints[lefthand].position
+		aim = rotate(joints[lefthand].position
 			- joints[righthand].position,
 			0.0f, rotation - 2.5f, 0.0f);
 		coeff = 0.15f;
 		break;
 	case handgun1:
 	case handgun2:
-		aim = DoRotation(joints[righthand].position
+		aim = rotate(joints[righthand].position
 			- joints[head].position * 0.35f
 			- joints[neck].position * 0.65f,
 			0.0f, player.playerrotation - 0.9f, 0.0f);
@@ -935,8 +934,8 @@ void renderLaser(Game* game)
 	aim = normalize(aim);
 	auto& coords = player.playercoords;
 	auto start = coords
-		+ DoRotation(joints[lefthand].position, 0.0f, rotation, 0.0f)
-		+ DoRotation(DoRotation(DoRotation(aim, 0.0f, -rotation, 0.0f),
+		+ rotate(joints[lefthand].position, 0.0f, rotation, 0.0f)
+		+ rotate(rotate(rotate(aim, 0.0f, -rotation, 0.0f),
 		                        90.0f, 0.0f, 0.0f),
 		             0.0f, rotation, 0) * coeff;
 	auto end = start + aim * 1000.0f;
@@ -1010,8 +1009,8 @@ void Game::Tick()
 
 	// Facing
 	XYZ facing {0, 0, -1};
-	facing = DoRotation(facing, -camera.rotation2, 0, 0);
-	facing = DoRotation(facing, 0, -camera.rotation, 0);
+	facing = rotate(facing, -camera.rotation2, 0, 0);
+	facing = rotate(facing, 0, -camera.rotation, 0);
 
 	XYZ flatfacing = facing;
 	flatfacing.y = 0;
@@ -1485,10 +1484,10 @@ void Game::Tick()
 
 				for (auto& joint : person[i].skeleton.joints) {
 					joint.position += joint.offset;
-					joint.position = DoRotation(joint.position, 0, person[i].playerrotation, 0);
+					joint.position = rotate(joint.position, 0, person[i].playerrotation, 0);
 					joint.position += person[i].playercoords;
 					joint.realoldposition = joint.position;
-					joint.velocity = DoRotation(joint.velocity, 0, person[i].playerrotation, 0);
+					joint.velocity = rotate(joint.velocity, 0, person[i].playerrotation, 0);
 					joint.velocity += person[i].velocity;
 					joint.velocity += person[i].facing * 4;
 				}
@@ -1554,7 +1553,7 @@ void Game::Tick()
 
 			for (int j = 0; j < max_joints; ++j) {
 				person[i].tempanimation.position[j][0]=person[i].skeleton.joints[j].position-person[i].playercoords;
-				person[i].tempanimation.position[j][0]=DoRotation(person[i].tempanimation.position[j][0],0,-person[i].playerrotation,0);
+				person[i].tempanimation.position[j][0]=rotate(person[i].tempanimation.position[j][0],0,-person[i].playerrotation,0);
 			}
 		}
 	}
@@ -1654,7 +1653,7 @@ void Game::Tick()
 				aimjoint = lefthand;
 			}
 			start = person[j].playercoords
-				+ DoRotation(person[j].skeleton.joints[aimjoint].position,
+				+ rotate(person[j].skeleton.joints[aimjoint].position,
 					0, person[j].playerrotation, 0);
 
 			if (j == 0 && person[j].grenphase) {
@@ -1663,10 +1662,10 @@ void Game::Tick()
 					start, aim * 200, 1.01);
 			}
 
-			auto startsub = DoRotation(aim,
+			auto startsub = rotate(aim,
 				0, -person[j].playerrotation, 0);
-			startsub = DoRotation(startsub, 90, 0, 0);
-			startsub *= DoRotation(startsub,
+			startsub = rotate(startsub, 90, 0, 0);
+			startsub *= rotate(startsub,
 				0, person[j].playerrotation,0);
 			switch (person[j].whichgun) {
 			case sniperrifle:
@@ -1787,7 +1786,7 @@ void Game::Tick()
 
 							finalwallhit=wallhit;
 
-							hitnorm=DoRotation(blocks[citytype[i][j]].normals[whichtri],0,cityrotation[i][j]*90,0);
+							hitnorm=rotate(blocks[citytype[i][j]].normals[whichtri],0,cityrotation[i][j]*90,0);
 
 							hitmove=move;
 
@@ -1952,7 +1951,7 @@ void Game::Tick()
 							totalarea=0;
 
 							for (auto& joint : person[whichhit].skeleton.joints) {
-								joint.position = DoRotation(joint.position, 0, person[whichhit].playerrotation, 0);
+								joint.position = rotate(joint.position, 0, person[whichhit].playerrotation, 0);
 								joint.position += person[whichhit].playercoords;
 								joint.realoldposition = joint.position;
 								joint.velocity = person[whichhit].velocity;
@@ -2000,12 +1999,12 @@ void Game::Tick()
 						person[whichhit].skeleton.offset=1;
 
 						for (auto& joint : person[whichhit].skeleton.joints) {
-							auto distance = sqrlen(DoRotation(joint.position, 0, person[whichhit].playerrotation, 0)
+							auto distance = sqrlen(rotate(joint.position, 0, person[whichhit].playerrotation, 0)
 								+ person[whichhit].playercoords
 								- hitstruct.hitlocation);
 							if(distance < 200) {
 								totalarea += 200 / distance;
-								joint.offset += DoRotation(aim * 200 / distance / totalarea * 10,
+								joint.offset += rotate(aim * 200 / distance / totalarea * 10,
 									0, -person[whichhit].playerrotation, 0);
 							}
 							if (sqrlen(joint.offset) > 36)
@@ -2025,7 +2024,7 @@ void Game::Tick()
 									for (int tmp = 0; tmp < 4; ++tmp)
 										sprites.MakeSprite(bloodspritedown, 0.8f, 1, 0.2f, 0.2f,
 											person[whichhit].skeleton.joints[j].position,
-											DoRotation(person[whichhit].skeleton.joints[j].velocity / 3,
+											rotate(person[whichhit].skeleton.joints[j].velocity / 3,
 												randUint(360), randUint(360), 0) / 5, 5);
 									person[whichhit].skeleton.DeleteJoint(j);
 									person[whichhit].skeleton.broken=1;
@@ -2234,7 +2233,7 @@ void Game::Tick()
 
 			if (whichtri != -1) {
 				impact = true;
-				auto normalrotated = DoRotation(blocks[citytype[wherex][wherey]].normals[whichtri], 0, cityrotation[wherex][wherey] * 90, 0);
+				auto normalrotated = rotate(blocks[citytype[wherex][wherey]].normals[whichtri], 0, cityrotation[wherex][wherey] * 90, 0);
 				if (sprites.size[i] > 1)
 					decals.MakeDecal(crater, wallhit, 9, normalrotated, whichtri, &blocks[citytype[wherex][wherey]], move, cityrotation[wherex][wherey] * 90);
 				sprites.location[i] = wallhit + normalrotated * 0.02f;
@@ -2318,7 +2317,7 @@ void Game::Tick()
 						person[j].longdead=1;
 						for (auto& joint : person[j].skeleton.joints) {
 							joint.realoldposition = joint.position
-								= DoRotation(joint.position,
+								= rotate(joint.position,
 									0, person[j].playerrotation, 0)
 								+ person[j].playercoords;
 
@@ -2342,12 +2341,12 @@ void Game::Tick()
 						person[j].skeleton.offset=1;
 
 						for (auto& joint : person[j].skeleton.joints) {
-							auto distance = sqrlen(DoRotation(joint.position, 0, person[j].playerrotation, 0)
+							auto distance = sqrlen(rotate(joint.position, 0, person[j].playerrotation, 0)
 								+ person[j].playercoords
 								- hitstruct.hitlocation);
 							if (distance < 200) {
 								totalarea += 200 / distance;
-								joint.offset += DoRotation(sprites.velocity[i] * 0.1 * 200 / distance / totalarea * 10, 0, -person[j].playerrotation, 0);
+								joint.offset += rotate(sprites.velocity[i] * 0.1 * 200 / distance / totalarea * 10, 0, -person[j].playerrotation, 0);
 							}
 							if (sqrlen(joint.offset) > 9) {
 								joint.offset = normalize(joint.offset) * 3;
@@ -2376,7 +2375,7 @@ void Game::Tick()
 			alSourcePlay(gSourceID[explosionsound]);
 
 			XYZ relation;
-			camerashake=1-findDistance(person[0].playercoords,sprites.location[i])/200;
+			camerashake = 1 - len(person[0].playercoords - sprites.location[i]) / 200;
 
 			overpoint=sprites.location[i];
 			overpoint.y+=3000;
@@ -2434,10 +2433,10 @@ void Game::Tick()
 					person[k].bjoint2 = &person[k].skeleton.joints[neck];
 
 					for (auto& joint : person[k].skeleton.joints) {
-						joint.position = DoRotation(joint.position, 0, person[k].playerrotation, 0);
+						joint.position = rotate(joint.position, 0, person[k].playerrotation, 0);
 						joint.position += person[k].playercoords;
 						joint.realoldposition = joint.position;
-						joint.velocity = DoRotation(joint.velocity, 0, person[k].playerrotation, 0);
+						joint.velocity = rotate(joint.velocity, 0, person[k].playerrotation, 0);
 						joint.velocity += person[k].velocity;
 						joint.velocity.x += randInt(-9, 9);
 						joint.velocity.y += randInt(-9, 9);
@@ -2448,7 +2447,7 @@ void Game::Tick()
 				person[k].longdead=1;
 				for (auto& joint : person[k].skeleton.joints) {
 					relation = normalize(joint.position - sprites.location[i]);
-					auto distance = findDistance(joint.position, sprites.location[i]);
+					auto distance = len(joint.position - sprites.location[i]);
 					if (distance > 1)
 						joint.velocity += relation / distance * 300;
 					else
@@ -2480,7 +2479,7 @@ void Game::Tick()
 
 	if(zoom)average=person[0].skeleton.joints[righthand].position;
 
-	if(person[0].skeleton.free==0&&thirdperson!=2)camera.position=person[0].playercoords+DoRotation(average,0,person[0].playerrotation,0);
+	if(person[0].skeleton.free==0&&thirdperson!=2)camera.position=person[0].playercoords+rotate(average,0,person[0].playerrotation,0);
 
 	if(person[0].skeleton.free==1&&thirdperson!=2)camera.position=average;
 
diff --git a/src/Globals.cpp b/src/Globals.cpp
index 2760674..b8f5d14 100644
--- a/src/Globals.cpp
+++ b/src/Globals.cpp
@@ -49,11 +49,6 @@ float fogcolorr;
 float fogcolorg;
 float fogcolorb;
 
-float d;
-float a1,a2,a3;
-float total,denom,mu;
-XYZ n,pa1,pa2,pa3;
-
 XYZ vel;
 XYZ midp;
 XYZ newpoint1,newpoint2;
diff --git a/src/Models.cpp b/src/Models.cpp
index a414008..acbbaa8 100644
--- a/src/Models.cpp
+++ b/src/Models.cpp
@@ -117,99 +117,35 @@ void Model::draw(float r, float g, float b)
 	glDrawArrays(GL_TRIANGLES, 0, TriangleNum*3);
 }
 
-int Model::LineCheck(XYZ p1,XYZ p2, XYZ *p)
+int Model::LineCheck(XYZ p1, XYZ p2, XYZ *p)
 {
-  	int j;
-	float distance;
-	float olddistance=9999999.0;
-	int intersecting=0;
-	int firstintersecting=-1;
-	XYZ point;
-	if (segmentIntersectsSphere(p1, p2, boundingspherecenter, boundingsphereradius))
-	for (j=0;j<TriangleNum;j++){
-		intersecting=LineFacetd(p1,p2,vertex[Triangles[j].vertex[0]],vertex[Triangles[j].vertex[1]],vertex[Triangles[j].vertex[2]],normals[j],&point);
-		if (intersecting == 0) continue;
-		distance=(point.x-p1.x)*(point.x-p1.x)+(point.y-p1.y)*(point.y-p1.y)+(point.z-p1.z)*(point.z-p1.z);
-		if((distance<olddistance||firstintersecting==-1)&&intersecting){olddistance=distance; firstintersecting=j; *p=point;}
+	int result = -1;
+	if (segmentIntersectsSphere(p1, p2, boundingspherecenter,
+	                            boundingsphereradius)) {
+		float olddistance = 9999999.0;
+		for (int j = 0; j < TriangleNum; ++j) {
+			XYZ point;
+			if (!LineFacetd(p1, p2,
+			                vertex[Triangles[j].vertex[0]],
+			                vertex[Triangles[j].vertex[1]],
+			                vertex[Triangles[j].vertex[2]],
+			                normals[j], &point))
+				continue;
+			float distance = sqrlen(point - p1);
+			if (distance < olddistance || result == -1) {
+				olddistance = distance;
+				result = j;
+				*p = point;
+			}
+		}
 	}
-	return firstintersecting;
+	return result;
 }
 
-int Model::LineCheck2(XYZ p1,XYZ p2, XYZ *p, XYZ move, float rotate)
+int Model::LineCheck2(XYZ p1, XYZ p2, XYZ *p, XYZ move, float deg_y)
 {
-  	int j;
-	float distance;
-	float olddistance=9999999.0;
-	int intersecting=0;
-	int firstintersecting=-1;
-	XYZ point;
-	p1=p1-move;
-	p2=p2-move;
-	if(rotate)p1=DoRotation(p1,0,-rotate,0);
-	if(rotate)p2=DoRotation(p2,0,-rotate,0);
-	if (segmentIntersectsSphere(p1, p2, boundingspherecenter, boundingsphereradius))
-	for (j=0;j<TriangleNum;j++){
-		intersecting=LineFacetd(p1,p2,vertex[Triangles[j].vertex[0]],vertex[Triangles[j].vertex[1]],vertex[Triangles[j].vertex[2]],normals[j],&point);
-		if (intersecting == 0) continue;
-		distance=(point.x-p1.x)*(point.x-p1.x)+(point.y-p1.y)*(point.y-p1.y)+(point.z-p1.z)*(point.z-p1.z);
-		if((distance<olddistance||firstintersecting==-1)&&intersecting){olddistance=distance; firstintersecting=j; *p=point;}
-	}
-
-	if(rotate)*p=DoRotation(*p,0,rotate,0);
-	*p=*p+move;
-	return firstintersecting;
-}
-
-int Model::LineCheck2(XYZ *p1,XYZ *p2, XYZ *p, XYZ *move, float *rotate)
-{
-  	int j;
-	float distance;
-	float olddistance=9999999.0;
-	int intersecting=0;
-	int firstintersecting=-1;
-	XYZ point;
-	*p1=*p1-*move;
-	*p2=*p2-*move;
-	if(*rotate)*p1=DoRotation(*p1,0,-*rotate,0);
-	if(*rotate)*p2=DoRotation(*p2,0,-*rotate,0);
-	if (segmentIntersectsSphere(*p1, *p2, boundingspherecenter, boundingsphereradius))
-	for (j=0;j<TriangleNum;j++){
-		intersecting = LineFacetd(*p1, *p2,
-			vertex[Triangles[j].vertex[0]],
-			vertex[Triangles[j].vertex[1]],
-			vertex[Triangles[j].vertex[2]],
-			normals[j], &point);
-		if (intersecting == 0) continue;
-		distance=(point.x-p1->x)*(point.x-p1->x)+(point.y-p1->y)*(point.y-p1->y)+(point.z-p1->z)*(point.z-p1->z);
-		if((distance<olddistance||firstintersecting==-1)&&intersecting){olddistance=distance; firstintersecting=j; *p=point;}
-	}
-
-	if(*rotate)*p=DoRotation(*p,0,*rotate,0);
-	*p=*p+*move;
-	return firstintersecting;
-}
-
-int Model::LineCheck3(XYZ p1,XYZ p2, XYZ *p, XYZ move, float rotate, float *d)
-{
-  	int j;
-	float distance;
-	float olddistance=9999999.0;
-	int intersecting=0;
-	int firstintersecting=-1;
-	XYZ point;
-	p1=p1-move;
-	p2=p2-move;
-	p1=DoRotation(p1,0,-rotate,0);
-	p2=DoRotation(p2,0,-rotate,0);
-	if (segmentIntersectsSphere(p1, p2, boundingspherecenter, boundingsphereradius))
-	for (j=0;j<TriangleNum;j++){
-		intersecting=LineFacetd(p1,p2,vertex[Triangles[j].vertex[0]],vertex[Triangles[j].vertex[1]],vertex[Triangles[j].vertex[2]],normals[j],&point);
-		if (intersecting == 0) continue;
-		distance=(point.x-p1.x)*(point.x-p1.x)+(point.y-p1.y)*(point.y-p1.y)+(point.z-p1.z)*(point.z-p1.z);
-		if((distance<olddistance||firstintersecting==-1)&&intersecting){olddistance=distance; firstintersecting=j; *p=point;}
-	}
-	*d=intersecting;
-	*p=DoRotation(*p,0,rotate,0);
-	*p=*p+move;
-	return firstintersecting;
+	int result = this->LineCheck(rotate(p1 - move, 0, -deg_y, 0),
+		rotate(p2 - move, 0, -deg_y, 0), p);
+	*p = rotate(*p, 0, deg_y, 0) + move;
+	return result;
 }
diff --git a/src/Models.h b/src/Models.h
index 5c68997..5c27d6f 100644
--- a/src/Models.h
+++ b/src/Models.h
@@ -34,10 +34,8 @@ public:
 
 	XYZ boundingspherecenter;
 	float boundingsphereradius;
-	int LineCheck(XYZ p1,XYZ p2, XYZ *p);
-	int LineCheck2(XYZ p1,XYZ p2, XYZ *p,XYZ move,float rotate);
-	int LineCheck2(XYZ *p1,XYZ *p2, XYZ *p,XYZ *move,float *rotate);
-	int LineCheck3(XYZ p1,XYZ p2, XYZ *p,XYZ move,float rotate,float *d);
+	int LineCheck(XYZ, XYZ, XYZ*);
+	int LineCheck2(XYZ, XYZ, XYZ*, XYZ, float);
 
 	void UpdateVertexArray();
 	void load(const char*);
diff --git a/src/Person.cpp b/src/Person.cpp
index 292269a..c644aab 100644
--- a/src/Person.cpp
+++ b/src/Person.cpp
@@ -67,8 +67,8 @@ HitStruct 	Person::BulletCollideWithPlayer(int who, XYZ start, XYZ end){
 	if(skeleton.free<1){
 		start=start-playercoords;
 		end=end-playercoords;
-		if(playerrotation)start=DoRotation(start,0,-playerrotation,0);
-		if(playerrotation)end=DoRotation(end,0,-playerrotation,0);
+		if(playerrotation)start=rotate(start,0,-playerrotation,0);
+		if(playerrotation)end=rotate(end,0,-playerrotation,0);
 	}
 	tempbulletloc[0]=start;
 	tempbulletloc[1]=end;
@@ -176,7 +176,7 @@ HitStruct 	Person::BulletCollideWithPlayer(int who, XYZ start, XYZ end){
 					glRotatef(-skeleton.muscles[j].rotate1+90,0,1,0);
 					glRotatef(-skeleton.muscles[j].rotate2+90,0,0,1);
 					glRotatef(-skeleton.muscles[j].rotate3,0,1,0);
-					glScalef(1,findDistance(skeleton.muscles[j].parent1->position,skeleton.muscles[j].parent2->position),1);
+					glScalef(1, len(skeleton.muscles[j].parent1->position - skeleton.muscles[j].parent2->position), 1);
 					glTranslatef(collisionpoint.x,collisionpoint.y,collisionpoint.z);
 					glGetFloatv(GL_MODELVIEW_MATRIX,M);
 					collisionpoint.x=M[12];
@@ -192,7 +192,7 @@ HitStruct 	Person::BulletCollideWithPlayer(int who, XYZ start, XYZ end){
 	}
 	}
 	if(skeleton.free<1){
-		if(playerrotation)hitstruct.hitlocation=DoRotation(hitstruct.hitlocation,0,playerrotation,0);
+		if(playerrotation)hitstruct.hitlocation=rotate(hitstruct.hitlocation,0,playerrotation,0);
 		hitstruct.hitlocation=hitstruct.hitlocation+playercoords;
 	}
 	return hitstruct;
@@ -215,7 +215,7 @@ void Person::DoAnimations(int who)
 		if (targetanimation == zombieeatanim && targetframe == 3) {
 			auto& joints = skeleton.joints;
 			auto head_joint = joints[head];
-			auto soundsrc = (DoRotation(head_joint.position,
+			auto soundsrc = (rotate(head_joint.position,
 				0, playerrotation, 0) + playercoords
 				- camera.position) / soundscalefactor;
 			playSound(gSourceID[bodyhitsound],
@@ -243,7 +243,7 @@ void Person::DoAnimations(int who)
 			targetanimation = getupfrontanim;
 			auto& joints = skeleton.joints;
 			auto head_joint = joints[head];
-			auto soundsrc = (DoRotation(head_joint.position,
+			auto soundsrc = (rotate(head_joint.position,
 				0, playerrotation, 0) + playercoords
 				- camera.position) / soundscalefactor;
 			ALfloat gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z};
@@ -259,11 +259,11 @@ void Person::DoAnimations(int who)
 			longdead = 1;
 			for (auto& joint : skeleton.joints) {
 				joint.position = playercoords
-					+ DoRotation(joint.position
+					+ rotate(joint.position
 						+ joint.offset,
 						0, playerrotation, 0);
 				joint.realoldposition = joint.position;
-				joint.velocity = DoRotation(joint.velocity,
+				joint.velocity = rotate(joint.velocity,
 					0, playerrotation, 0);
 			}
 		}
@@ -313,11 +313,11 @@ void Person::DoAnimations(int who)
 		if (who == 0)
 			playerrotation2 = camera.rotation2;
 		XYZ facing {0.0f, 0.0f, 1.0f};
-		XYZ facinghalf = DoRotation(DoRotation(facing,
+		XYZ facinghalf = rotate(rotate(facing,
 			playerrotation2 / 2, 0, 0), 0, -7, 0);
-		facing = DoRotation(facing, playerrotation2, 0, 0);
-		XYZ facingright = DoRotation(facing, 0, -90, 0);
-		XYZ facingdown = DoRotation(facing, 90, 0, 0);
+		facing = rotate(facing, playerrotation2, 0, 0);
+		XYZ facingright = rotate(facing, 0, -90, 0);
+		XYZ facingdown = rotate(facing, 90, 0, 0);
 		XYZ rotatearound;
 		XYZ oldpos;
 		switch (whichgun) {
@@ -367,14 +367,14 @@ void Person::DoAnimations(int who)
 							skeleton.joints[i].position-=(animation[idleanim].position[neck][0]-skeleton.joints[neck].position);
 						}
 						skeleton.joints[i].position+=facingright*0.1;
-						skeleton.joints[i].position=rotatearound+DoRotation(skeleton.joints[i].position-rotatearound,(playerrotation2/2-10)*aimamount,0,0);
+						skeleton.joints[i].position=rotatearound+rotate(skeleton.joints[i].position-rotatearound,(playerrotation2/2-10)*aimamount,0,0);
 						skeleton.joints[i].position=skeleton.joints[i].position*(aimamount)+oldpos*(1-aimamount);
 					}
 					if(whichgun==shotgun){
 						oldpos=skeleton.joints[i].position;
 						skeleton.joints[i].position=animation[assaultrifleaimanim].position[i][0];
 						if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position-=(animation[idleanim].position[neck][0]-skeleton.joints[neck].position);
-						skeleton.joints[i].position=rotatearound+DoRotation(skeleton.joints[i].position-rotatearound,(playerrotation2/2)*aimamount,0,0);
+						skeleton.joints[i].position=rotatearound+rotate(skeleton.joints[i].position-rotatearound,(playerrotation2/2)*aimamount,0,0);
 						if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position+=facingdown*.2;
 						else skeleton.joints[i].position-=facingdown*.02;
 						if(skeleton.joints[i].label==righthand)skeleton.joints[i].position=skeleton.joints[lefthand].position-facinghalf*2;
@@ -384,7 +384,7 @@ void Person::DoAnimations(int who)
 						oldpos=skeleton.joints[i].position;
 						skeleton.joints[i].position=animation[assaultrifleaimanim].position[i][0];
 						if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position-=(animation[idleanim].position[neck][0]-skeleton.joints[neck].position);
-						skeleton.joints[i].position=rotatearound+DoRotation(skeleton.joints[i].position-rotatearound,(playerrotation2/2)*aimamount,0,0);
+						skeleton.joints[i].position=rotatearound+rotate(skeleton.joints[i].position-rotatearound,(playerrotation2/2)*aimamount,0,0);
 						if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position+=facingdown*.2;
 						else skeleton.joints[i].position-=facingdown*.02;
 						if(skeleton.joints[i].label==righthand)skeleton.joints[i].position=skeleton.joints[lefthand].position-facinghalf*2;
@@ -394,7 +394,7 @@ void Person::DoAnimations(int who)
 						oldpos=skeleton.joints[i].position;
 						skeleton.joints[i].position=animation[pistolaimanim].position[i][0];
 						if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position-=(animation[idleanim].position[neck][0]-skeleton.joints[neck].position);
-						skeleton.joints[i].position=rotatearound+DoRotation(skeleton.joints[i].position-rotatearound,(playerrotation2/2)*aimamount,0,0);
+						skeleton.joints[i].position=rotatearound+rotate(skeleton.joints[i].position-rotatearound,(playerrotation2/2)*aimamount,0,0);
 						if(currentanimation==crouchanim||targetanimation==crouchanim){skeleton.joints[i].position+=facingright*.15;skeleton.joints[i].position+=facingdown*.3;}
 						else skeleton.joints[i].position-=facingdown*.1;
 						skeleton.joints[i].position=skeleton.joints[i].position*(aimamount)+oldpos*(1-aimamount);
@@ -403,7 +403,7 @@ void Person::DoAnimations(int who)
 						oldpos=skeleton.joints[i].position;
 						skeleton.joints[i].position=animation[pistolaimanim].position[i][0];
 						if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position-=(animation[idleanim].position[neck][0]-skeleton.joints[neck].position);
-						skeleton.joints[i].position=rotatearound+DoRotation(skeleton.joints[i].position-rotatearound,(playerrotation2/2)*aimamount,0,0);
+						skeleton.joints[i].position=rotatearound+rotate(skeleton.joints[i].position-rotatearound,(playerrotation2/2)*aimamount,0,0);
 						if(currentanimation==crouchanim||targetanimation==crouchanim){skeleton.joints[i].position+=facingright*.15;skeleton.joints[i].position+=facingdown*.3;}
 						else skeleton.joints[i].position-=facingdown*.1;
 						skeleton.joints[i].position=skeleton.joints[i].position*(aimamount)+oldpos*(1-aimamount);
@@ -463,11 +463,11 @@ void Person::DoAnimations(int who)
 				}
 				if(attackframe==animation[grenadethrowanim].numframes-1&&ammo>0){
 					ammo=-1;
-					sprites.MakeSprite(grenadesprite, 1, 1, 1, 1, DoRotation(skeleton.joints[righthand].position,0,playerrotation,0)+playercoords, DoRotation(facing,0,playerrotation,0)*30+velocity, 1);
-					sprites.MakeSprite(spoonsprite, 1, 1, 1, 1, DoRotation(skeleton.joints[righthand].position,0,playerrotation,0)+playercoords, DoRotation(facing,0,playerrotation,0)*10+velocity, 1);
-					sprites.MakeSprite(pinsprite, 1, 1, 1, 1, DoRotation(skeleton.joints[lefthand].position,0,playerrotation,0)+playercoords, facing*.1+velocity, 1);
+					sprites.MakeSprite(grenadesprite, 1, 1, 1, 1, rotate(skeleton.joints[righthand].position,0,playerrotation,0)+playercoords, rotate(facing,0,playerrotation,0)*30+velocity, 1);
+					sprites.MakeSprite(spoonsprite, 1, 1, 1, 1, rotate(skeleton.joints[righthand].position,0,playerrotation,0)+playercoords, rotate(facing,0,playerrotation,0)*10+velocity, 1);
+					sprites.MakeSprite(pinsprite, 1, 1, 1, 1, rotate(skeleton.joints[lefthand].position,0,playerrotation,0)+playercoords, facing*.1+velocity, 1);
 
-					XYZ soundsrc = (DoRotation(skeleton.joints[righthand].position, 0, playerrotation, 0)
+					XYZ soundsrc = (rotate(skeleton.joints[righthand].position, 0, playerrotation, 0)
 						+ playercoords - camera.position) / soundscalefactor;
 					ALfloat gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z};
 					alSourcefv(gSourceID[grenadethrowsound], AL_POSITION, gLoc);
@@ -481,12 +481,12 @@ void Person::DoAnimations(int who)
 			for (auto& joint : skeleton.joints)
 				if (!joint.lower)
 					joint.position = rotatearound
-						+ DoRotation(joint.position - rotatearound, playerrotation2 / 2, 0, 0);
+						+ rotate(joint.position - rotatearound, playerrotation2 / 2, 0, 0);
 				else if (joint.label != groin)
-					joint.position = DoRotation(joint.position, 0, playerlowrotation - playerrotation, 0);
+					joint.position = rotate(joint.position, 0, playerlowrotation - playerrotation, 0);
 			rotatearound = skeleton.joints[neck].position;
 			skeleton.joints[head].position = rotatearound
-				+ DoRotation(skeleton.joints[head].position - rotatearound, playerrotation2 / 2, 0, 0);
+				+ rotate(skeleton.joints[head].position - rotatearound, playerrotation2 / 2, 0, 0);
 		}
 
 		skeleton.DoConstraints();
@@ -558,7 +558,7 @@ void Person::DoAnimationslite(int who)
 		if (targetanimation == zombieeatanim && targetframe == 3) {
 			auto& joints = skeleton.joints;
 			auto head_joint = joints[head];
-			auto soundsrc = (DoRotation(head_joint.position,
+			auto soundsrc = (rotate(head_joint.position,
 				0, playerrotation, 0) + playercoords
 				- camera.position) / soundscalefactor;
 			playSound(gSourceID[bodyhitsound],
@@ -644,7 +644,7 @@ void Person::control()
 	if (!onground && (forwards || right)) {
 		auto rotation = playerrotation
 			- right * (forwards ? forwards * 45 : 90);
-		facing = DoRotation({0, 0, 1}, 0, rotation, 0);
+		facing = rotate({0, 0, 1}, 0, rotation, 0);
 		velocity += facing * multiplier * 4;
 	}
 }
@@ -688,7 +688,7 @@ void Person::DoStuff(int who)
 	    && currentanimation != getupfrontanim)
 		control();
 
-	facing = DoRotation({0, 0, 1}, 0, playerlowrotation, 0);
+	facing = rotate({0, 0, 1}, 0, playerlowrotation, 0);
 	if (backwardsanim)
 		facing *= -1;
 
@@ -713,16 +713,17 @@ void Person::FindRotationGun(XYZ start, XYZ target)
 
 	temppoint1=start;
 	temppoint2=target;
-	distance=findDistance(temppoint1,temppoint2);
+	distance = len(temppoint1 - temppoint2);
 	gunrotate2=asin((temppoint1.y-temppoint2.y)/distance)*rad2deg;
 	temppoint1.y=0;
 	temppoint2.y=0;
-	gunrotate1=acos((temppoint1.z-temppoint2.z)/findDistance(temppoint1,temppoint2))*rad2deg;
+	gunrotate1 = rad2deg * acos((temppoint1.z - temppoint2.z)
+		/ len(temppoint1 - temppoint2));
 	if(temppoint1.x>temppoint2.x)gunrotate1=360-gunrotate1;
 	tempforward=target-start;
-	tempforward=DoRotation(tempforward,-90,0,0);
-	tempforward=DoRotation(tempforward,0,gunrotate1-90,0);
-	tempforward=DoRotation(tempforward,0,0,gunrotate2-90);
+	tempforward=rotate(tempforward,-90,0,0);
+	tempforward=rotate(tempforward,0,gunrotate1-90,0);
+	tempforward=rotate(tempforward,0,0,gunrotate2-90);
 	tempforward.y=0;
 	tempforward = normalize(tempforward);
 	gunrotate3=acos(0-tempforward.z)*rad2deg;
@@ -974,8 +975,8 @@ int Person::DrawSkeleton(int who)
 				//Facing
 				XYZ facing {0};
 				facing.z = 1;
-				facing = DoRotation(facing, camera.rotation2, 0, 0);
-				XYZ facingdown = DoRotation(facing, 90, 0, 0);
+				facing = rotate(facing, camera.rotation2, 0, 0);
+				XYZ facingdown = rotate(facing, 90, 0, 0);
 
 				skeleton.specialforward[1] *= 1 - aimamount;
 				skeleton.specialforward[1] += facingdown * aimamount;
diff --git a/src/Quaternions.cpp b/src/Quaternions.cpp
index 2c01da9..9b32dc0 100644
--- a/src/Quaternions.cpp
+++ b/src/Quaternions.cpp
@@ -52,22 +52,17 @@ bool PointInTriangle(XYZ *p, XYZ normal, XYZ *p1, XYZ *p2, XYZ *p3)
 	return bInter;
 }
 
-extern float d;
-extern float a1,a2,a3;
-extern float total,denom,mu;
-extern XYZ pa1,pa2,pa3,n;
-
 float LineFacetd(XYZ p1,XYZ p2,XYZ pa,XYZ pb,XYZ pc, XYZ n, XYZ *p)
 {
 
    //Calculate the parameters for the plane
-   d = - n.x * pa.x - n.y * pa.y - n.z * pa.z;
+   float d = - n.x * pa.x - n.y * pa.y - n.z * pa.z;
 
    //Calculate the position on the line that intersects the plane
-   denom = n.x * (p2.x - p1.x) + n.y * (p2.y - p1.y) + n.z * (p2.z - p1.z);
+   float denom = n.x * (p2.x - p1.x) + n.y * (p2.y - p1.y) + n.z * (p2.z - p1.z);
    if (abs(denom) < 0.0000001)        // Line and plane don't intersect
       return 0;
-   mu = - (d + n.x * p1.x + n.y * p1.y + n.z * p1.z) / denom;
+   float mu = - (d + n.x * p1.x + n.y * p1.y + n.z * p1.z) / denom;
    p->x = p1.x + mu * (p2.x - p1.x);
    p->y = p1.y + mu * (p2.y - p1.y);
    p->z = p1.z + mu * (p2.z - p1.z);
@@ -77,46 +72,3 @@ float LineFacetd(XYZ p1,XYZ p2,XYZ pa,XYZ pb,XYZ pc, XYZ n, XYZ *p)
    if(!PointInTriangle( p, n, &pa, &pb, &pc)){return 0;}
    return 1;
 }
-
-float findDistance(XYZ point1, XYZ point2){
-	return sqrt((point1.x-point2.x)*(point1.x-point2.x)+(point1.y-point2.y)*(point1.y-point2.y)+(point1.z-point2.z)*(point1.z-point2.z));
-}
-
-XYZ DoRotation(XYZ thePoint, float xang, float yang, float zang){
-	XYZ newpoint;
-	if(xang){
-		xang*=6.283185;
-		xang/=360;
-	}
-	if(yang){
-		yang*=6.283185;
-		yang/=360;
-	}
-	if(zang){
-		zang*=6.283185;
-		zang/=360;
-	}
-
-	if(yang){
-	newpoint.z=thePoint.z*cos(yang)-thePoint.x*sin(yang);
-	newpoint.x=thePoint.z*sin(yang)+thePoint.x*cos(yang);
-	thePoint.z=newpoint.z;
-	thePoint.x=newpoint.x;
-	}
-
-	if(zang){
-	newpoint.x=thePoint.x*cos(zang)-thePoint.y*sin(zang);
-	newpoint.y=thePoint.y*cos(zang)+thePoint.x*sin(zang);
-	thePoint.x=newpoint.x;
-	thePoint.y=newpoint.y;
-	}
-
-	if(xang){
-	newpoint.y=thePoint.y*cos(xang)-thePoint.z*sin(xang);
-	newpoint.z=thePoint.y*sin(xang)+thePoint.z*cos(xang);
-	thePoint.z=newpoint.z;
-	thePoint.y=newpoint.y;
-	}
-
-	return thePoint;
-}
diff --git a/src/Quaternions.h b/src/Quaternions.h
index f1fbe6b..e01740a 100644
--- a/src/Quaternions.h
+++ b/src/Quaternions.h
@@ -43,17 +43,16 @@ extern "C" {
 #endif // __cplusplus
 	float dotProduct(struct XYZ, struct XYZ);
 	float sqrlen(struct XYZ);
+	float len(struct XYZ);
 	struct XYZ crossProduct(struct XYZ, struct XYZ);
 	struct XYZ normalize(struct XYZ);
 	void reflect(struct XYZ*, struct XYZ);
 	bool segmentIntersectsSphere(struct XYZ, struct XYZ, struct XYZ, float);
+	struct XYZ rotate(struct XYZ, float, float, float);
 
 	float LineFacetd(struct XYZ p1, struct XYZ p2,
 		struct XYZ pa, struct XYZ pb, struct XYZ pc,
 		struct XYZ n, struct XYZ *p);
-	struct XYZ DoRotation(struct XYZ thePoint,
-		float xang, float yang, float zang);
-	float findDistance(struct XYZ point1, struct XYZ point2);
 
 	void getFrustum(float (*)[4]);
 	int cubeInFrustum(float (*)[4], float, float, float, float);
diff --git a/src/Skeleton.cpp b/src/Skeleton.cpp
index 23892b8..62861b4 100644
--- a/src/Skeleton.cpp
+++ b/src/Skeleton.cpp
@@ -48,7 +48,7 @@ void Joint::DoConstraint()
 void Muscle::DoConstraint(int broken)
 {
 	oldlength=length;
-	relaxlength=findDistance(parent1->position,parent2->position);
+	relaxlength = len(parent1->position - parent2->position);
 
 	if(type==boneconnect)strength=1;
 	if(type==constraint)strength=0;
@@ -131,7 +131,7 @@ void Skeleton::DoConstraints(Model *collide, XYZ *move, float rotation)
 				offset = true;
 				if (whichtri != -1
 				    && collide->normals[whichtri].y <= 0.8) {
-					normalrotated = DoRotation(collide->normals[whichtri], 0, rotation, 0);
+					normalrotated = rotate(collide->normals[whichtri], 0, rotation, 0);
 					pos = impact + normalrotated * offset;
 					reflect(&joints[i].velocity, normalrotated);
 					joints[i].velocity *= 0.3;
@@ -264,11 +264,12 @@ void Skeleton::FindRotationJoint(int which)
 
 	temppoint1=joints[which].position;
 	temppoint2=joints[which].parent->position;
-	distance=findDistance(temppoint1,temppoint2);
+	distance = len(temppoint1 - temppoint2);
 	joints[which].rotate2=asin((temppoint1.y-temppoint2.y)/distance)*rad2deg;
 	temppoint1.y=0;
 	temppoint2.y=0;
-	joints[which].rotate1=acos((temppoint1.z-temppoint2.z)/findDistance(temppoint1,temppoint2))*rad2deg;
+	joints[which].rotate1 = rad2deg * acos((temppoint1.z - temppoint2.z)
+		/ len(temppoint1 - temppoint2));
 	if(temppoint1.x>temppoint2.x)joints[which].rotate1=360-joints[which].rotate1;
 	if(joints[which].label==head)tempforward=specialforward[0];
 	else if(joints[which].label==rightshoulder||joints[which].label==rightelbow||joints[which].label==rightwrist||joints[which].label==righthand)tempforward=specialforward[1];
@@ -277,8 +278,8 @@ void Skeleton::FindRotationJoint(int which)
 	else if(joints[which].label==lefthip||joints[which].label==leftknee||joints[which].label==leftankle)tempforward=specialforward[4];
 	else if(!joints[which].lower)tempforward=forward;
 	else if(joints[which].lower)tempforward=lowforward;
-	tempforward=DoRotation(tempforward,0,joints[which].rotate1-90,0);
-	tempforward=DoRotation(tempforward,0,0,joints[which].rotate2-90);
+	tempforward=rotate(tempforward,0,joints[which].rotate1-90,0);
+	tempforward=rotate(tempforward,0,0,joints[which].rotate2-90);
 	tempforward.y=0;
 	tempforward = normalize(tempforward);
 	joints[which].rotate3=acos(0-tempforward.z)*rad2deg;
@@ -292,12 +293,12 @@ void Skeleton::FindRotationMuscle(int which)
 
 	temppoint1=muscles[which].parent1->position;
 	temppoint2=muscles[which].parent2->position;
-	distance=findDistance(temppoint1,temppoint2);
+	distance = len(temppoint1 - temppoint2);
 	muscles[which].rotate2=asin((temppoint1.y-temppoint2.y)/distance)*rad2deg;
 	temppoint1.y=0;
 	temppoint2.y=0;
-	muscles[which].rotate1=acos((temppoint1.z-temppoint2.z)/findDistance(temppoint1,temppoint2));
-	muscles[which].rotate1*=360/6.28;
+	muscles[which].rotate1 = rad2deg * acos((temppoint1.z - temppoint2.z)
+		/ len(temppoint1 - temppoint2));
 	if(temppoint1.x>temppoint2.x)muscles[which].rotate1=360-muscles[which].rotate1;
 	if(muscles[which].parent1->label==head)tempforward=specialforward[0];
 	else if(muscles[which].parent1->label==rightshoulder||muscles[which].parent1->label==rightelbow||muscles[which].parent1->label==rightwrist)tempforward=specialforward[1];
@@ -306,8 +307,8 @@ void Skeleton::FindRotationMuscle(int which)
 	else if(muscles[which].parent1->label==lefthip||muscles[which].parent1->label==leftknee||muscles[which].parent1->label==leftankle)tempforward=specialforward[4];
 	else if(!muscles[which].parent1->lower)tempforward=forward;
 	else if(muscles[which].parent1->lower)tempforward=lowforward;
-	tempforward=DoRotation(tempforward,0,muscles[which].rotate1-90,0);
-	tempforward=DoRotation(tempforward,0,0,muscles[which].rotate2-90);
+	tempforward=rotate(tempforward,0,muscles[which].rotate1-90,0);
+	tempforward=rotate(tempforward,0,0,muscles[which].rotate2-90);
 	tempforward.y=0;
 	tempforward = normalize(tempforward);
 	muscles[which].rotate3=acos(0-tempforward.z)*rad2deg;
diff --git a/src/geom.zig b/src/geom.zig
index 910f355..96add58 100644
--- a/src/geom.zig
+++ b/src/geom.zig
@@ -18,6 +18,7 @@
 // along with Black Shades.  If not, see <https://www.gnu.org/licenses/>.
 
 const Child = std.meta.Child;
+const degreesToRadians = std.math.degreesToRadians;
 const std = @import("std");
 
 const c = @import("cimport.zig");
@@ -39,6 +40,11 @@ fn norm(v: anytype) Child(@TypeOf(v)) {
     return @sqrt(dot(v, v));
 }
 
+export fn len(v: XYZ) f32 {
+    const u = @bitCast(@Vector(3, f32), v);
+    return norm(u);
+}
+
 const XYZ = extern struct { x: f32, y: f32, z: f32 };
 
 export fn crossProduct(u: XYZ, v: XYZ) XYZ {
@@ -61,6 +67,22 @@ export fn reflect(v: XYZ, n: XYZ) XYZ {
     return @bitCast(XYZ, u - m * @splat(3, dot(u, m) * 2));
 }
 
+fn rotate2d(i: *f32, j: *f32, a: f32) void {
+    if (a == 0) return;
+    const x = i.*;
+    const y = j.*;
+    i.* = x * @cos(a) - y * @sin(a);
+    j.* = x * @sin(a) + y * @cos(a);
+}
+
+export fn rotate(v: XYZ, deg_x: f32, deg_y: f32, deg_z: f32) XYZ {
+    var u = v;
+    rotate2d(&u.z, &u.x, degreesToRadians(f32, deg_y));
+    rotate2d(&u.x, &u.y, degreesToRadians(f32, deg_z));
+    rotate2d(&u.y, &u.z, degreesToRadians(f32, deg_x));
+    return u;
+}
+
 export fn segmentIntersectsSphere(a: XYZ, b: XYZ, j: XYZ, r: f32) bool {
     // FIXME: call directly with vectors
     const p = @bitCast(@Vector(3, f32), a);