@@ -173,6 +173,15 @@ AFRAME.registerComponent('environment', {
173173 this . dressing = document . createElement ( 'a-entity' ) ;
174174 this . dressing . classList . add ( 'environmentDressing' ) ;
175175
176+ // add static-body component to the ground if physics available
177+ const physicsAvail = ! ! this . el . sceneEl . getAttribute ( 'physics' ) ;
178+ if ( physicsAvail ) {
179+ this . ground . setAttribute ( 'static-body' , 'shape' , 'none' ) ;
180+ // Specifying hull as shape works but is slow. We create
181+ // a Heightfield shape at the same time as modifying the plane
182+ // geometry and attach it to the body.
183+ }
184+
176185 this . gridCanvas = null ;
177186 this . gridTexture = null ;
178187
@@ -463,14 +472,26 @@ AFRAME.registerComponent('environment', {
463472 return ;
464473 }
465474
475+ var segments = resolution - 1 ;
476+ var planeSize = this . STAGE_SIZE + 2 ;
477+ var planeSizeHalf = planeSize / 2 ;
478+ var segmentSize = planeSize / segments ;
466479 if ( ! this . groundGeometry ) {
467- this . groundGeometry = new THREE . PlaneGeometry ( this . STAGE_SIZE + 2 , this . STAGE_SIZE + 2 , resolution - 1 , resolution - 1 ) ;
480+ this . groundGeometry = new THREE . PlaneGeometry ( planeSize , planeSize , segments , segments ) ;
468481 }
469482 var perlin = new PerlinNoise ( ) ;
470483 var verts = this . groundGeometry . vertices ;
471484 var numVerts = this . groundGeometry . vertices . length ;
472485 var frequency = 10 ;
473486 var inc = frequency / resolution ;
487+ var physicsAvail = ! ! this . el . sceneEl . getAttribute ( 'physics' ) ;
488+ if ( physicsAvail ) {
489+ var maxH = 0 ;
490+ var matrix = [ ] ;
491+ for ( var j = 0 ; j < resolution ; j ++ ) {
492+ matrix . push ( new Float32Array ( resolution ) ) ;
493+ }
494+ }
474495
475496 for ( var i = 0 , x = 0 , y = 0 ; i < numVerts ; i ++ ) {
476497 if ( this . data . ground == 'flat' ) {
@@ -512,6 +533,16 @@ AFRAME.registerComponent('environment', {
512533 // set height
513534 verts [ i ] . z = h ;
514535
536+ // construct matrix to create the Heightfield
537+ if ( physicsAvail ) {
538+ // We reverse the calculation that is done when creating the
539+ // PlaneGeometry to get back the original x and y for the matrix.
540+ matrix [ Math . round ( ( verts [ i ] . x + planeSizeHalf ) / segmentSize ) ] [ Math . round ( ( verts [ i ] . y + planeSizeHalf ) / segmentSize ) ] = h * this . data . groundYScale ;
541+ if ( h > maxH ) {
542+ maxH = h ;
543+ }
544+ }
545+
515546 // calculate next x,y ground coordinates
516547 x += inc ;
517548 if ( x >= 10 ) {
@@ -520,6 +551,27 @@ AFRAME.registerComponent('environment', {
520551 }
521552 }
522553
554+
555+ if ( physicsAvail ) {
556+ // Create the heightfield
557+ var hfShape = new CANNON . Heightfield ( matrix , {
558+ elementSize : segmentSize ,
559+ minValue : 0 ,
560+ maxValue : maxH * this . data . groundYScale
561+ } ) ;
562+ hfShape . offset = new THREE . Vector3 ( - planeSize / 2 , - planeSize / 2 , 0 ) ;
563+ this . ground . addEventListener ( 'body-loaded' , ( ) => {
564+ this . ground . body . addShape ( hfShape , hfShape . offset , hfShape . orientation ) ;
565+ // Show wireframe
566+ if ( this . el . sceneEl . systems . physics . debug ) {
567+ var bodyComponent = this . ground . components [ 'static-body' ] ;
568+ var createWireframe = bodyComponent . createWireframe . bind ( bodyComponent ) ;
569+ createWireframe ( this . ground . body , hfShape ) ;
570+ this . el . sceneEl . object3D . add ( bodyComponent . wireframe ) ;
571+ }
572+ } ) ;
573+ }
574+
523575 this . groundGeometry . computeFaceNormals ( ) ;
524576 if ( this . data . flatShading ) {
525577 this . groundGeometry . computeFlatVertexNormals ( ) ;
0 commit comments