javascript - Cannon.JS make walls solid -
i making go of three.js , cannon.js, stuck being able make walls solid, or solid doesn't move , hold player back. http://www.trepaning.com/3js/sea3d/elviscollidewalls.html
here code have far. insight appreciated. prefer figuring stuff out on own, 1 thing of making walls solid holding me @ moment, , appreciate info me on hump.
if ( ! detector.webgl ) detector.addgetwebglmessage(); var initscene; var margin = 10; var marginside = 0; var width = window.innerwidth || ( 2 + 2 * marginside ); //var width = window.innerwidth/3 || ( 2 + 2 * marginside ); //var height = window.innerheight/3 || ( 2 + 2 * margin ); var height = window.innerheight || ( 2 + 2 * margin ); var screen_width = width -2 * marginside; var screen_height = height -2 * margin; var far = 10000; var day = 0; var stats, camera, scene, renderer; var mesh, geometry; var sunlight, pointlight, ambientlight, hemilight; var parameters var clock = new three.clock(); var inrender = true; var inresize = false; // cannon physics var world; var worldscale = 100; var timestep = 1/60; var walls=[], balls=[], ballmeshes=[], boxes=[], boxmeshes=[]; var solidmaterial; var playermaterialphy; var playerrigid; var playerphysicsmesh; var unitsize = 250 var wallheight = unitsize / 3; var map = [ // 1 2 3 4 5 6 7 8 9 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], // 0 [1, 1, 0, 0, 0, 0, 0, 1, 1, 1,], // 1 [1, 1, 0, 0, 2, 0, 0, 0, 0, 1,], // 2 [1, 0, 0, 1, 0, 2, 0, 0, 0, 1,], // 3 [1, 0, 0, 2, 0, 0, 2, 1, 0, 1,], // 4 [1, 0, 0, 0, 2, 0, 0, 0, 0, 1,], // 5 [1, 1, 1, 0, 0, 0, 0, 0, 1, 1,], // 6 [1, 1, 1, 0, 0, 0, 0, 0, 1, 1,], // 7 [1, 1, 1, 1, 1, 1, 0, 0, 1, 1,], // 8 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1,], // 9 ], mapw = map.length, maph = map[0].length; // player var loader; var player; var playermaterial; var playermap = { map:undefined, normal:undefined}; var players=[]; var playername = "legoelvis"; var scalefactor = 5; var velocity = {x : 0, z : 0}; var playercontrols = { moveforward: false, movebackward: false, moveleft: false, moveright: false, bodyorientation: 0, maxspeed: 275, maxreversespeed: -275, frontacceleration: 600, backacceleration: 600, frontdecceleration: 600, angularspeed: 2.5, speed: 0 }; var shadowconfig = { visible: false, near: 750, far: 4000, fov: 75, bias: -0.0002, darkness: 0.5, resolution:1024 }; var playerconfig = { name: "", loading: 0, scale: 1, clonenumber: 30, clone: false }; var lightconfig = { ambient: 0x554b3b, fog : 0x00283f }; var materialconfig = { shininess : 0, specular: 1, normalscalex: 0, normalscaley: 0, bias:0, bumpscale: 2, metal:false }; var sky; var skycubenight, skycubeday; var skyshader; initscene = function () { // renderer renderer = new three.webglrenderer( { clearcolor: lightconfig.fog, clearalpha: 1, antialias: true } ); renderer.setsize( screen_width, screen_height ); renderer.setclearcolor( lightconfig.fog, 1 ); renderer.domelement.style.position = "absolute"; document.getelementbyid( 'viewport' ).appendchild( renderer.domelement ); renderer.shadowmapenabled = true; renderer.shadowmaptype = three.pcfsoftshadowmap; renderer.gammainput = true; renderer.gammaoutput = true; renderer.physicallybasedshading = true; // scene scene = new three.scene(); scene.fog = new three.fog( lightconfig.fog , 1000, far ); // camera camera = new three.perspectivecamera( 45, screen_width / screen_height, 2, far ); camera.position.set( 50, 300, 350 ); // camera control controls = new three.orbitcontrols( camera, renderer.domelement ); controls.center.set( 0, 0, 0 ); controls.keys = []; controls.maxpolarangle = torad(90); controls.userrotatespeed = 1.8; controls.zoomspeed = 1.6; controls.userpanspeed = 0.8; // ground var mapground = three.imageutils.loadtexture( "images/legoelvis.jpg" ); mapground.anisotropy = renderer.getmaxanisotropy(); mapground.repeat.set( 100, 100 ); mapground.wraps = mapground.wrapt = three.repeatwrapping; mapground.magfilter = three.nearestfilter; mapground.format = three.rgbformat; var groundmaterial = new three.meshphongmaterial( { shininess: 10, ambient: 0x444444, color: 0xffffff, specular: 0xffffff, map: mapground, metal: false } ); var planegeometry = new three.planegeometry( 100, 100 ); var ground = new three.mesh( planegeometry, groundmaterial ); ground.position.set( 0, 0, 0 ); ground.rotation.x = - math.pi / 2; ground.scale.set( 1000, 1000, 1000 ); ground.receiveshadow = true; scene.add( ground ); initlights(); initphysics(); loadsea3dmodel(); stats = new stats(); document.getelementbyid('my-stat').appendchild(stats.domelement); // listeners window.addeventlistener( 'resize', onwindowresize, false ); document.addeventlistener( 'keydown', onkeydown, false ); document.addeventlistener( 'keyup', onkeyup, false ); // tween parameters = { control: 0 }; animate(); } //----------------------------------------------------- // light //----------------------------------------------------- function initlights() { var sunintensity = 0.8; var pointintensity = 0.3; var pointcolor = 0xffffff; var skyintensity = 1; ambientlight = new three.ambientlight( lightconfig.ambient ); scene.add( ambientlight ); hemilight = new three.hemispherelight( 0xffffff, 0xffffff, 0.6 ); hemilight.color.sethsl( 0.63, 0.05, 0 ); hemilight.groundcolor.sethex( 0xe4c8a0 ); hemilight.position.set( 0, 400, 0 ); scene.add( hemilight ); pointlight = new three.pointlight( lightconfig.moon, pointintensity, 5000 ); pointlight.position.set( -1000, 0, -1000 ); scene.add( pointlight ); sunlight = new three.spotlight( lightconfig.sun, sunintensity, 0, math.pi/2, 1 ); sunlight.position.set( 1000, 2000, 1000 ); sunlight.castshadow = true; sunlight.shadowcameravisible = shadowconfig.visible; sunlight.shadowcameranear = shadowconfig.near; sunlight.shadowcamerafar = shadowconfig.far; sunlight.shadowcamerafov = shadowconfig.fov; sunlight.shadowbias = shadowconfig.bias; sunlight.shadowdarkness = shadowconfig.darkness * sunintensity; sunlight.shadowmapwidth = shadowconfig.resolution; sunlight.shadowmapheight = shadowconfig.resolution; scene.add( sunlight ); } function enablecascadeshadow() { renderer.shadowmapcascade = true; sunlight.shadowcascade = true; sunlight.shadowcascadecount = 3; sunlight.shadowcascadenearz = [ -1.000, 0.995, 0.998 ]; sunlight.shadowcascadefarz = [ 0.995, 0.998, 1.000 ]; sunlight.shadowcascadewidth = [ shadowconfig.resolution, shadowconfig.resolution, shadowconfig.resolution ]; sunlight.shadowcascadeheight = [ shadowconfig.resolution, shadowconfig.resolution, shadowconfig.resolution ]; } //----------------------------------------------------- // resize //----------------------------------------------------- function onwindowresize( event ) { inresize = true; //document.getelementbyid("viewport").style.background = '#222222'; screen_width = window.innerwidth - 2 * marginside; screen_height = window.innerheight - 2 * margin; camera.aspect = screen_width / screen_height; camera.updateprojectionmatrix(); renderer.setsize( screen_width, screen_height ); } //----------------------------------------------------- // keyboard //----------------------------------------------------- function onkeydown ( event ) { switch ( event.keycode ) { case 38: /*up*/ case 87: /*w*/ case 90: /*z*/ playercontrols.moveforward = true; break; case 40: /*down*/ case 83: /*s*/ playercontrols.movebackward = true; break; case 37: /*left*/ case 65: /*a*/ case 81: /*q*/ playercontrols.moveleft = true; break; case 39: /*right*/ case 68: /*d*/ playercontrols.moveright = true; break; } } function onkeyup ( event ) { switch( event.keycode ) { case 38: /*up*/ case 87: /*w*/ case 90: /*z*/ playercontrols.moveforward = false; break; case 40: /*down*/ case 83: /*s*/ playercontrols.movebackward = false; break; case 37: /*left*/ case 65: /*a*/ case 81: /*q*/ playercontrols.moveleft = false; break; case 39: /*right*/ case 68: /*d*/ playercontrols.moveright = false; break; } }; //----------------------------------------------------- // sea3d //----------------------------------------------------- function loadsea3dmodel() { loader = new three.sea3d( false ); //loader.matrixautoupdate = true; //loader.invertcamera = true; loader.oncomplete = function( e ) { player = loader.getmesh(playername); player.play("idle"); player.scale.set( playerconfig.scale*3, playerconfig.scale*3, -playerconfig.scale*3 ); scene.add( player ); creatplayerphysics(); }; //loader.load( 'folder/'+playername+'.sea' ); loader.load( 'models/legoelvis.sea' ); } // player animation function updateplayer(delta) { if (playercontrols.moveforward){ if (player.currentanimation.name == "idle") player.play("walk"); } else if (playercontrols.movebackward){ if (player.currentanimation.name == "idle") player.play("walk"); } else { if(player.currentanimation.name == "walk") player.play("idle"); } three.animationhandler.update( delta ); updateplayermove(delta); } // player move function updateplayermove( delta ) { playercontrols.maxreversespeed = -playercontrols.maxspeed; if ( playercontrols.moveforward ) playercontrols.speed = three.math.clamp( playercontrols.speed + delta * playercontrols.frontacceleration, playercontrols.maxreversespeed, playercontrols.maxspeed ); if ( playercontrols.movebackward ) playercontrols.speed = three.math.clamp( playercontrols.speed - delta * playercontrols.backacceleration, playercontrols.maxreversespeed, playercontrols.maxspeed ); // orientation based on controls // (don't stand while turning) var dir = 1; if ( playercontrols.moveleft ) { playercontrols.bodyorientation += delta * playercontrols.angularspeed; playercontrols.speed = three.math.clamp( playercontrols.speed + dir * delta * playercontrols.frontacceleration, playercontrols.maxreversespeed, playercontrols.maxspeed ); } if ( playercontrols.moveright ) { playercontrols.bodyorientation -= delta * playercontrols.angularspeed; playercontrols.speed = three.math.clamp( playercontrols.speed + dir * delta * playercontrols.frontacceleration, playercontrols.maxreversespeed, playercontrols.maxspeed ); } // speed decay if ( ! ( playercontrols.moveforward || playercontrols.movebackward ) ) { if ( playercontrols.speed > 0 ) { var k = exponentialeaseout( playercontrols.speed / playercontrols.maxspeed ); playercontrols.speed = three.math.clamp( playercontrols.speed - k * delta * playercontrols.frontdecceleration, 0, playercontrols.maxspeed ); } else { var k = exponentialeaseout( playercontrols.speed / playercontrols.maxreversespeed ); playercontrols.speed = three.math.clamp( playercontrols.speed + k * delta * playercontrols.backacceleration, playercontrols.maxreversespeed, 0 ); } } // displacement var forwarddelta = playercontrols.speed * delta; velocity.x = math.sin( playercontrols.bodyorientation ) * forwarddelta; velocity.z = math.cos( playercontrols.bodyorientation ) * forwarddelta; player.position.x += velocity.x; player.position.z += velocity.z; player.position.y = playerconfig.scale*scalefactor; // steering player.rotation.y = playercontrols.bodyorientation; if(controls){ //controls.target.set( player.position.x, player.position.y, player.position.z ); camera.position.x += velocity.x; camera.position.z += velocity.z; controls.center.set( player.position.x, player.position.y, player.position.z ); } if(playerrigid){ //playerrigid.position.set(player.position.x, player.position.y+3, player.position.z ); playerrigid.position.set(player.position.x, player.position.y+80, player.position.z+15 ); playerrigid.quaternion.setfromaxisangle(new cannon.vec3(0,1,0),player.rotation.y); } }; function exponentialeaseout( k ) { return k === 1 ? 1 : - math.pow( 2, - 10 * k ) + 1; }; //----------------------------------------------------- // render loop //----------------------------------------------------- function animate() { requestanimationframe( animate ); if(inrender || inresize){ //if(ispad)padtest(); //updatecamera(); var delta = clock.getdelta(); if(player!=null)updateplayer(delta); updatephysics(); render(); stats.update(); } inresize = false; } function render() { tween.update(); controls.update(); scene.fog.color.sethsl( 0.63, 0.05, parameters.control ); renderer.setclearcolor( scene.fog.color, 1 ); pointlight.intensity = - parameters.control * 0.5 + 1; hemilight.color.sethsl( 0.63, 0.05, parameters.control ) sunlight.shadowdarkness = shadowconfig.darkness * sunlight.intensity; renderer.render( scene, camera ); } function tell(s){ document.getelementbyid("debug").innerhtml = s; } //----------------------------------------------------- // physics //----------------------------------------------------- function initphysics() { world = new cannon.world(); world.quatnormalizeskip = 0; world.quatnormalizefast = false; var solver = new cannon.gssolver(); world.defaultcontactmaterial.contactequationstiffness = 1e9; world.defaultcontactmaterial.contactequationregularizationtime = 4; solver.iterations = 3; solver.tolerance = 0.1; world.gravity.set(0,-9.82*worldscale,0);//world.gravity.set(0,-9.82,0); // m/s² world.broadphase = new cannon.naivebroadphase(); // create slippery material (friction coefficient = 0.0) physicsmaterial = new cannon.material("slipperymaterial"); solidmaterial = new cannon.material("solidmaterial"); playermaterialphy = new cannon.material("playermat"); var physicscontactmaterial = new cannon.contactmaterial(physicsmaterial, physicsmaterial, 0.0, 0.3 ); var playercontactmaterial = new cannon.contactmaterial(playermaterialphy, playermaterialphy, 0.0, 0.3 ); var solidcontactmaterial = new cannon.contactmaterial(solidmaterial, solidmaterial, 0.2, 0.6 ); world.addcontactmaterial(physicscontactmaterial); world.addcontactmaterial(playercontactmaterial); world.addcontactmaterial(solidcontactmaterial); // create infinie plane var groundshape = new cannon.plane(); var groundbody = new cannon.rigidbody(0,groundshape,physicsmaterial); groundbody.quaternion.setfromaxisangle(new cannon.vec3(1,0,0),-math.pi/2); world.add(groundbody); createboxeobject(); createballobject(); } function creatplayerphysics() { if(playerphysicsmesh){ scene.remove(playerphysicsmesh); playerphysicsmesh.geometry.dispose(); } if(playerrigid)world.remove(playerrigid); //player body var halfextents = new cannon.vec3(0.5*worldscale,playerconfig.scale*80, 0.25*worldscale); var playershape = new cannon.box(halfextents); playerrigid = new cannon.rigidbody(0,playershape, playermaterialphy); world.add(playerrigid); playerrigid.lineardamping=0.01; playerrigid.angulardamping=0.01; var boxgeometry = new three.cubegeometry(halfextents.x*2,halfextents.y*2,halfextents.z*2); playerphysicsmesh = new three.mesh( boxgeometry ); scene.add(playerphysicsmesh); playerphysicsmesh.usequaternion = true; playerphysicsmesh.castshadow = false; playerphysicsmesh.receiveshadow = false; showplayerphysics(); } function showplayerphysics() { //if(optionconfig.showplayerhitbox)playerphysicsmesh.visible = true; //else playerphysicsmesh.visible = true; playerphysicsmesh.visible = true; } function createballobject() { var s = worldscale; var mat = new three.meshlambertmaterial( { color: 0xdddddd } ); var radius; var mass = 4; var sphereshape; for(var i=0; i<5; i++){ radius = (0.2+(math.random()*0.8))*s; sphereshape = new cannon.sphere(radius); ballgeometry = new three.spheregeometry(radius, 32, 32 ); var spherebody = new cannon.rigidbody(mass,sphereshape,physicsmaterial); //spherebody.lineardamping = 0.9; var x = ((math.random()-0.5)*20)*s; var y = (1 + (math.random()-0.5)*1)*s; var z = ((math.random()-0.5)*20)*s; spherebody.position.set(x,y,z); spherebody.lineardamping=0.03; spherebody.angulardamping=0.03; world.add(spherebody); var ballmesh = new three.mesh( ballgeometry, mat ); scene.add(ballmesh); ballmesh.usequaternion = true; ballmesh.castshadow = true; ballmesh.receiveshadow = true; // add array balls.push(spherebody); ballmeshes.push(ballmesh); } } function createboxeobject() { var s = worldscale; var material = new three.meshlambertmaterial( { color: 0x222222 } ); // add boxes var sx, xy, xz; var halfextents = new cannon.vec3(1*s,1*s,1*s); var boxshape = new cannon.box(halfextents); var boxgeometry = new three.cubegeometry(halfextents.x*2,halfextents.y*2,halfextents.z*2); for(var i=0; i<5; i++){ sx= 0.2+(math.random()*0.8); sy= 0.2+(math.random()*0.8); sz= 0.2+(math.random()*0.8); halfextents = new cannon.vec3(sx*s,sy*s,sz*s); boxshape = new cannon.box(halfextents); boxgeometry = new three.cubegeometry(halfextents.x*2,halfextents.y*2,halfextents.z*2); var x = ((math.random()-0.5)*20)*s; var y = (1 + (math.random()-0.5)*1)*s; var z = ((math.random()-0.5)*20)*s; var boxbody = new cannon.rigidbody(9,boxshape, solidmaterial); var boxmesh = new three.mesh( boxgeometry, material ); world.add(boxbody); scene.add(boxmesh); boxbody.position.set(x,y,z); //boxmesh.position.set(x,y,z); boxbody.quaternion.setfromaxisangle(new cannon.vec3(0,0,0),torad(math.random()*360)); boxmesh.castshadow = true; boxmesh.receiveshadow = true; boxmesh.usequaternion = true; boxes.push(boxbody); boxmeshes.push(boxmesh); } function createobstacle() { obstaclemesh = new three.cubegeometry(150, 50, 50) obstaclematerial = new three.meshlambertmaterial( { color: 0x666666 } ); obstacleobject = new three.mesh(obstaclemesh, obstaclematerial); obstacleobject.position.set(0, 26, 200); obstacleobject.castshadow = true; obstacleobject.receiveshadow = true; scene.add(obstacleobject); } createobstacle(); function setupscene() { var units = mapw; // geometry: walls var cube = new three.cubegeometry(unitsize, wallheight, unitsize); var materials = [ new three.meshlambertmaterial({map: three.imageutils.loadtexture('images/legoelvisr.jpg')}), //wall 1 new three.meshlambertmaterial({map: three.imageutils.loadtexture('images/legoelvisg.jpg')}), //wall 2 ]; (var = 0; < mapw; i++) { (var j = 0, m = map[i].length; j < m; j++) { if (map[i][j]) { var wall = new three.mesh(cube, materials[map[i][j]-1]); wall.position.x = (i - units/2) * unitsize; wall.position.y = wallheight/2; wall.position.z = (j - units/2) * unitsize; wall.castshadow = true; wall.receiveshadow = true; scene.add(wall); } } } } setupscene(); // add linked boxes var size = 0.5*s; var = new cannon.vec3(size,size,size*0.1); var boxshape = new cannon.box(he); var mass = 0; var space = 0.1*size; var n=5, last; var boxgeometry = new three.cubegeometry(he.x*2,he.y*2,he.z*2); for(var i=0; i<n; i++){ var boxbody = new cannon.rigidbody(mass,boxshape, solidmaterial); var boxmesh = new three.mesh( boxgeometry, material ); boxbody.position.set(5*s,((n-i)*(size*2+2*space) + size*2+space)-150,0); boxbody.lineardamping=0.01; boxbody.angulardamping=0.01; boxmesh.usequaternion = true; boxmesh.castshadow = true; boxmesh.receiveshadow = true; world.add(boxbody); scene.add(boxmesh); boxes.push(boxbody); boxmeshes.push(boxmesh); if(i!=0){ // connect body last 1 var c1 = new cannon.pointtopointconstraint(boxbody,new cannon.vec3(-size,size+space,0),last,new cannon.vec3(-size,-size-space,0)); var c2 = new cannon.pointtopointconstraint(boxbody,new cannon.vec3(size,size+space,0),last,new cannon.vec3(size,-size-space,0)); world.addconstraint(c1); world.addconstraint(c2); } else { mass=0.3; } last = boxbody; } } function updatephysics() { if(!world) return; world.step(timestep); // update player mesh test if(playerrigid !== undefined){ playerrigid.position.copy(playerphysicsmesh.position); playerrigid.quaternion.copy(playerphysicsmesh.quaternion); } // update ball positions for(var i=0; i<balls.length; i++){ balls[i].position.copy(ballmeshes[i].position); balls[i].quaternion.copy(ballmeshes[i].quaternion); } // update box positions for(var i=0; i<boxes.length; i++){ boxes[i].position.copy(boxmeshes[i].position); boxes[i].quaternion.copy(boxmeshes[i].quaternion); } } //----------------------------------------------------- // math //----------------------------------------------------- function torad(value) { return value * math.pi / 180; } window.onload = initscene;
when update physics in updateplayermove
, set position of corresponding cannon.js body. body never have chance update position since override position time.
setting position of bodies makes physics unstable. you'll large , buggy overlaps. and, of course, player able walk through walls.
try controlling player body via velocity instead. cannon.js provide response on player you, , physics become stable:
playerrigid.velocity.set(vx,vy,vz);
Comments
Post a Comment