Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function World(){
- var objects = [];
- var epsilon = 0.5;
- const gravity = 0;
- var objectIndex = 0;
- var createObject = function(type = 'sphere',
- pos = new THREE.Vector3(),
- force = new THREE.Vector3(),
- rot = new THREE.Vector3(0,0,0),
- angle = 0,
- static = false,
- mass = 1.0,
- normal = null,
- color) {
- console.log('create');
- var geometry, material;
- var vel = new THREE.Vector3();
- var acc = new THREE.Vector3(0.0, 0.0, 0.0);
- if(type === "plane"){
- color = color || "#103F97"
- geometry = new THREE.PlaneGeometry(40, 40);
- geometry.elementsNeedUpdate = true;
- material = new THREE.MeshBasicMaterial( { color: color} );
- } else if(type === "sphere"){
- color = color || "#433F81"
- geometry = new THREE.SphereGeometry(1.0, 10.0, 10.0);
- material = new THREE.MeshBasicMaterial( { color: color } );
- }
- else{
- type = 'box';
- geometry = new THREE.BoxGeometry(1.0, 1.0, 1.0);
- material = new THREE.MeshBasicMaterial( { color: "#433F81" } );
- }
- var newMesh = new THREE.Mesh(geometry, material);
- newMesh.setRotationFromAxisAngle(rot, angle);
- newMesh.position.set(pos.x, pos.y, pos.z);
- scene.add(newMesh);
- objects.push({
- mesh: newMesh,
- type: type,
- mass: mass,
- moment_of_inertia: 0.0,
- pos: pos,
- rot: rot,
- vel: vel,
- acc: acc,
- static: static,
- force: force,
- normal: normal
- });
- compute_moment_of_inertia(objects[objectIndex])
- objectIndex++;
- }
- var compute_moment_of_inertia = function(object){
- if (object.type === "sphere"){
- object.moment_of_inertia = 2.0 / 5.0 * object.mass * object.mesh.geometry.parameters.radius ** 2;
- } else if(object.type === "box"){
- object.moment_of_inertia = 1.0 / 12.0 * object.mass * (object.mesh.geometry.parameters.width ** 2 +
- object.mesh.geometry.parameters.height ** 2);
- }
- }
- var compute_force_applied = function() {
- for(var key = 0 ;key < objects.length;key++){
- var obj = objects[key];
- obj.force.y += (obj.mass * gravity);
- if (obj.force.x == 0 && obj.force.y == 0 && obj.force.z == 0) continue;
- obj.acc = obj.force.divideScalar(obj.mass);
- }
- }
- var detect_collision = function() {
- for(var key1 = 0;key1 < objects.length - 1;key1++){
- var obj1 = objects[key1];
- for(var key2 = key1 + 1;key2 < objects.length;key2++){
- var obj2 = objects[key2];
- if(obj1.type == "sphere" && obj2.type == "sphere"){
- var centers_distance = obj1.pos.distanceTo(obj2.pos);
- if(centers_distance <= obj1.mesh.geometry.parameters.radius + obj2.mesh.geometry.parameters.radius){
- solve_collision(key1, key2);
- }
- }
- if((obj1.type == "plane" && obj2.type == "sphere")||
- (obj1.type == "sphere" && obj2.type == "plane")){
- var key_plane, key_sphere;
- if(obj1.type == 'plane'){
- var obj_plane = obj1;
- var obj_sphere = obj2;
- key_plane = key1;
- key_sphere = key2;
- }else{
- var obj_plane = obj2;
- var obj_sphere = obj1;
- key_plane = key2;
- key_sphere = key1;
- }
- var bbs = new THREE.Box3();
- var bbp = new THREE.Box3();
- bbs.setFromObject(obj_sphere.mesh);
- bbp.setFromObject(obj_plane.mesh);
- if(bbs.intersectsBox(bbp)){
- contact_point = new THREE.Vector3(obj_sphere.pos.x - obj_plane.normal.x * obj_sphere.mesh.geometry.parameters.radius
- , obj_sphere.pos.y - obj_plane.normal.y * obj_sphere.mesh.geometry.parameters.radius
- , obj_sphere.pos.z - obj_plane.normal.z * obj_sphere.mesh.geometry.parameters.radius);
- solve_collision_plane(key_sphere, key_plane,contact_point,obj_plane.normal);
- }
- }
- }
- }
- }
- var solve_collision_plane = function(key_sphere, key_plane, contact_point, normal){
- var obj_sphere = objects[key_sphere];
- var obj_plane = objects[key_plane];
- var newSphereVel = compute_impulse(key_sphere, key_plane, contact_point, normal);
- obj_sphere.vel.sub(newSphereVel);
- }
- var solve_collision = function(key1, key2){
- obj1 = objects[key1];
- obj2 = objects[key2];
- var newVel1 = compute_impulse(key1,key2);
- var newVel2 = compute_impulse(key2,key1);
- obj1.vel.add(newVel1);
- obj2.vel.add(newVel2);
- }
- var compute_impulse = function(key1, key2, contact_point = null){
- obj1 = objects[key1];
- obj2 = objects[key2];
- var vel1 = new THREE.Vector3(obj1.vel.x, obj1.vel.y, obj1.vel.z);
- var vel2 = new THREE.Vector3(obj2.vel.x, obj2.vel.y, obj2.vel.z);
- var pos1 = new THREE.Vector3(obj1.pos.x, obj1.pos.y, obj1.pos.z);
- if(obj2.type === "plane"){
- var pos2 = contact_point;
- }
- else var pos2 = new THREE.Vector3(obj2.pos.x, obj2.pos.y, obj2.pos.z);
- var velr = new THREE.Vector3();
- var n = new THREE.Vector3();
- velr.addVectors(vel1,vel2);
- n.subVectors((pos1), (pos2));
- n = n.divideScalar(pos1.distanceTo(pos2));
- var pre_distance = pos1.distanceTo(pos2);
- var tmp1 = new THREE.Vector3(pos1.x, pos1.y, pos1.z);
- var tmp2 = new THREE.Vector3(pos2.x, pos2.y, pos2.z);
- var velRel1 = new THREE.Vector3(obj1.vel.x, obj1.vel.y, obj1.vel.z);
- var velRel2 = new THREE.Vector3(obj2.vel.x, obj2.vel.y, obj2.vel.z);
- velRel1.dot(n);
- velRel2.dot(n);
- var post_distance = (tmp1.add(velRel1).distanceTo(tmp2.add(velRel2)));
- if(post_distance > pre_distance){
- return new THREE.Vector3(0,0,0);
- }
- var velRelPre = new THREE.Vector3();
- velRelPre.subVectors(velRel1,velRel2);
- var epsilon_tmp;
- if(contact_point != null){
- if(velRelPre < 0.5) epsilon_tmp = 0;
- else epsilon_tmp = 0.6;
- }
- else epsilon_tmp = epsilon;
- var j = (-(1 + epsilon_tmp) * velRelPre.length()) / (1/obj1.mass + 1/obj2.mass);
- var newVel1 = new THREE.Vector3(n.x, n.y, n.z);
- newVel1.multiplyScalar(j);
- newVel1.divideScalar(obj1.mass);
- return newVel1;
- }
- var updatePosition = function(){
- detect_collision();
- compute_force_applied();
- for(var key in objects){
- var currObj = objects[key];
- currObj.pos.add(currObj.vel);
- currObj.vel.add(currObj.acc);
- currObj.mesh.position.set(currObj.pos.x, currObj.pos.y, currObj.pos.z);
- }
- }
- return{
- objects: objects,
- create: createObject,
- update: updatePosition
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement