plunkerで liquidfun その3

# 概要
plunkerで liquidfunやってみた。
揺れる瓶、やってみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/285ee38c-04f1-e4f2-3211-10b494891c18.png)

# サンプルコード

```

var container;
var world = null;
var threeRenderer;
var renderer;
var camera;
var scene;
var objects = [];
var timeStep = 1.0 / 60.0;
var velocityIterations = 8;
var positionIterations = 3;
var test = {};
var projector = new THREE.Projector();
var planeZ = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0);
var g_groundBody = null;
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
function printErrorMsg(msg) {
	var domElement = document.createElement('div');
	domElement.style.textAlign = 'center';
	domElement.innerHTML = msg;
	document.body.appendChild(domElement);
}
var render = function() {
	renderer.currentVertex = 0;
	if (test.Step !== undefined)
	{
		test.Step();
	} 
	else 
	{
		Step();
	}
	renderer.draw();
	threeRenderer.render(scene, camera);
	requestAnimationFrame(render);
};
var ResetWorld = function() {
	if (world !== null) 
	{
		while (world.joints.length > 0) 
		{
			world.DestroyJoint(world.joints[0]);
		}
		while (world.bodies.length > 0)
		{
			world.DestroyBody(world.bodies[0]);
		}
		while (world.particleSystems.length > 0)
		{
			world.DestroyParticleSystem(world.particleSystems[0]);
		}
	}
	camera.position.x = 0;
	camera.position.y = 0;
	camera.position.z = 100;
};
var Step = function() {
	world.Step(timeStep, velocityIterations, positionIterations);
};
function QueryCallback(point) {
	this.point = point;
	this.fixture = null;
}
QueryCallback.prototype.ReportFixture = function(fixture) {
	var body = fixture.body;
	if (body.GetType() === b2_dynamicBody) 
	{
		var inside = fixture.TestPoint(this.point);
		if (inside) 
		{
			this.fixture = fixture;
			return true;
		}
	}
	return false;
};
function onWindowResize() {
	camera.aspect = window.innerWidth / window.innerHeight;
	camera.updateProjectionMatrix();
	threeRenderer.setSize(window.innerWidth, window.innerHeight);
}
function getMouseCoords(event) {
	var mouse = new THREE.Vector3();
	mouse.x = (event.clientX / windowWidth) * 2 - 1;
	mouse.y = -(event.clientY / windowHeight) * 2 + 1;
	mouse.z = 0.5;
	projector.unprojectVector(mouse, camera);
	var dir = mouse.sub(camera.position).normalize();
	var distance = -camera.position.z / dir.z;
	var pos = camera.position.clone().add(dir.multiplyScalar(distance));
	var p = new b2Vec2(pos.x, pos.y);
	return p;
}
function TestWaveMachine() {
	camera.position.y = 1;
	camera.position.z = 3.5;
	var bd = new b2BodyDef();
	var ground = world.CreateBody(bd);
	bd.type = b2_dynamicBody;
	bd.allowSleep = false;
	bd.position.Set(0, 1);
	var body = world.CreateBody(bd);
	var b1 = new b2PolygonShape();
	b1.SetAsBoxXYCenterAngle(0.05, 1, new b2Vec2(2, 0), 0);
	body.CreateFixtureFromShape(b1, 5);
	var b2 = new b2PolygonShape();
	b2.SetAsBoxXYCenterAngle(0.05, 1, new b2Vec2(-2, 0), 0);
	body.CreateFixtureFromShape(b2, 5);
	var b3 = new b2PolygonShape();
	b3.SetAsBoxXYCenterAngle(2, 0.05, new b2Vec2(0, 1), 0);
	body.CreateFixtureFromShape(b3, 5);
	var b4 = new b2PolygonShape();
	b4.SetAsBoxXYCenterAngle(2, 0.05, new b2Vec2(0, -1), 0);
	body.CreateFixtureFromShape(b4, 5);
	var jd = new b2RevoluteJointDef();
	jd.motorSpeed = 0.05 * Math.PI;
	jd.maxMotorTorque = 1e7;
	//jd.enableMotor = true;
	this.joint = jd.InitializeAndCreate(ground, body, new b2Vec2(0, 1));
	this.time = 0;
	var psd = new b2ParticleSystemDef();
	psd.radius = 0.03;
	psd.dampingStrength = 0.2;
	var particleSystem = world.CreateParticleSystem(psd);
	var box = new b2PolygonShape();
	box.SetAsBoxXYCenterAngle(0.9, 0.9, new b2Vec2(0, 1.0), 0);
	var particleGroupDef = new b2ParticleGroupDef();
	particleGroupDef.shape = box;
	var particleGroup = particleSystem.CreateParticleGroup(particleGroupDef);
}
TestWaveMachine.prototype.Step = function() {
	world.Step(timeStep, velocityIterations, positionIterations);
	this.time += 1 / 60;
	this.joint.SetMotorSpeed(0.05 * Math.cos(this.time) * Math.PI);
}
function testSwitch(testName) {
	ResetWorld();
	world.SetGravity(new b2Vec2(0, -10));
	var bd = new b2BodyDef;
	g_groundBody = world.CreateBody(bd);
	test = new window[testName];
}
function Testbed(obj) {
	var that = this;
	document.addEventListener('keypress', function(event) {
		if (test.Keyboard !== undefined)
		{
			test.Keyboard(String.fromCharCode(event.which));
		}
	});
	document.addEventListener('keyup', function(event) {
		if (test.KeyboardUp !== undefined) 
		{
			test.KeyboardUp(String.fromCharCode(event.which));
		}
	});
	document.addEventListener('mousedown', function(event) {
		var p = getMouseCoords(event);
		var aabb = new b2AABB;
		var d = new b2Vec2;
		d.Set(0.01, 0.01);
		b2Vec2.Sub(aabb.lowerBound, p, d);
		b2Vec2.Add(aabb.upperBound, p, d);
		var queryCallback = new QueryCallback(p);
		world.QueryAABB(queryCallback, aabb);
		if (queryCallback.fixture) 
		{
			var body = queryCallback.fixture.body;
			var md = new b2MouseJointDef;
			md.bodyA = g_groundBody;
			md.bodyB = body;
			md.target = p;
			md.maxForce = 1000 * body.GetMass();
			that.mouseJoint = world.CreateJoint(md);
			body.SetAwake(true);
		}
		if (test.MouseDown !== undefined)
		{
			test.MouseDown(p);
		}
	});
	document.addEventListener('mousemove', function(event) {
		var p = getMouseCoords(event);
		if (that.mouseJoint) 
		{
			that.mouseJoint.SetTarget(p);
		}
		if (test.MouseMove !== undefined) 
		{
			test.MouseMove(p);
		}
	});
	document.addEventListener('mouseup', function(event) {
		if (that.mouseJoint)
		{
			world.DestroyJoint(that.mouseJoint);
			that.mouseJoint = null;
		}
		if (test.MouseUp !== undefined)
		{
			test.MouseUp(getMouseCoords(event));
		}
	});
	window.addEventListener('resize', onWindowResize, false);
	testSwitch("TestWaveMachine");
	render();
}
function initTestbed() {
	camera = new THREE.PerspectiveCamera(70, windowWidth / windowHeight, 1, 1000);
	try 
	{
		threeRenderer = new THREE.WebGLRenderer();
	}
	catch(error) 
	{
		printErrorMsg('<p>Sorry, your browser does not support WebGL.</p>'
				+ '<p>This testbed application uses WebGL to quickly draw'
				+ ' LiquidFun particles.</p>'
				+ '<p>LiquidFun can be used without WebGL, but unfortunately'
				+ ' this testbed cannot.</p>'
				+ '<p>Have a great day!</p>');
		return;
	}
	threeRenderer.setClearColor(0xEEEEEE);
	threeRenderer.setSize(windowWidth, windowHeight);
	camera.position.x = 0;
	camera.position.y = 0;
	camera.position.z = 100;
	scene = new THREE.Scene();
	camera.lookAt(scene.position);
	document.body.appendChild(this.threeRenderer.domElement);
	this.mouseJoint = null;
	renderer = new Renderer();
	var gravity = new b2Vec2(0, -10);
	world = new b2World(gravity);
	Testbed();
}
initTestbed();



```

# 成果物

https://embed.plnkr.co/plunk/KpyMfUwYkznY2q9U


以上。