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