GroundedSkybox.js 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. import { BackSide, Mesh, MeshBasicMaterial, SphereGeometry, Vector3 } from 'three';
  2. /**
  3. * A ground-projected skybox. The height is how far the camera that took the photo was above the ground -
  4. * a larger value will magnify the downward part of the image. By default the object is centered at the camera,
  5. * so it is often helpful to set skybox.position.y = height to put the ground at the origin. Set the radius
  6. * large enough to ensure your user's camera stays inside.
  7. */
  8. class GroundedSkybox extends Mesh {
  9. constructor( map, height, radius, resolution = 128 ) {
  10. if ( height <= 0 || radius <= 0 || resolution <= 0 ) {
  11. throw new Error( 'GroundedSkybox height, radius, and resolution must be positive.' );
  12. }
  13. const geometry = new SphereGeometry( radius, 2 * resolution, resolution );
  14. const pos = geometry.getAttribute( 'position' );
  15. const tmp = new Vector3();
  16. for ( let i = 0; i < pos.count; ++ i ) {
  17. tmp.fromBufferAttribute( pos, i );
  18. if ( tmp.y < 0 ) {
  19. // Smooth out the transition from flat floor to sphere:
  20. const y1 = - height * 3 / 2;
  21. const f =
  22. tmp.y < y1 ? - height / tmp.y : ( 1 - tmp.y * tmp.y / ( 3 * y1 * y1 ) );
  23. tmp.multiplyScalar( f );
  24. tmp.toArray( pos.array, 3 * i );
  25. }
  26. }
  27. pos.needsUpdate = true;
  28. super( geometry, new MeshBasicMaterial( { map, side: BackSide } ) );
  29. }
  30. }
  31. export { GroundedSkybox };