1
\$\begingroup\$

I have multiple planes whose vertices are transformed to a position on a sphere in the vertex shader. The GLSL function called pointToSphere transforms a point p to a position on a sphere with a radius of 100 units centered around localcenter.

I need to find a way to calculate the distance between the newly transformed planes and some position C on the CPU side. My algorithm has N number of planes for each side, and I need to find the distance between each plane and point C, not the entire sphere.

This doesn’t work plane.distanceTo(C)

enter image description here

CODE EXAMPLE:

let camera, scene,rtCamera,renderTarget,rtScene, renderer;
let uniforms, mesh, w;
let bbox  = new THREE.Box3();

renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setClearColor('white');
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);

function vertexShader() {
  return `
    uniform vec3 wTl;
    uniform vec3 ps;
 vec3 pointToSphere(vec3 p, vec3 localCenter){
    return 100.0*normalize(p-localCenter) + localCenter;
  }

    
varying vec3 v3n;
    void main() {
      vec3 newPosition   =  pointToSphere(position,wTl) ;
      gl_Position = projectionMatrix  * modelViewMatrix * vec4( newPosition, 1.0 ) ;
    }
  `
}

function fragmentShader(){
  return `
    uniform vec3 ucolor;
    void main() {
      gl_FragColor  = vec4(ucolor,1.0);
    }
`
}





init();

function init() {
    w = 100
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 0.001, 100000);
    camera.position.z = 250;
    scene.add(camera);

    let controls = new THREE.OrbitControls(camera, renderer.domElement);

    var front = buildMesh();
    var fg = new THREE.Group(front)
    fg.add(front)
  
    var back = buildMesh();
    var bg = new THREE.Group(back)
    bg.add(back)
    bg.position.z = -w;
    bg.rotation.y=(Math.PI)

    var right = buildMesh();
    var rg = new THREE.Group(right)
    rg.add(right)
    rg.position.z = -((w)/2);
    rg.position.x =  ((w)/2);
    rg.rotation.y = (Math.PI/2)

    var left = buildMesh();
    var lg = new THREE.Group(left)
    lg.add(left)
    lg.position.z = -((w)/2);
    lg.position.x = -((w)/2);
    lg.rotation.y=(-Math.PI/2)

    var top = buildMesh();
    var tg = new THREE.Group(top)
    tg.add(top)
    tg.position.z = -((w)/2);
    tg.position.y = ((w)/2);
    tg.rotation.x=(-Math.PI/2)

    var bot = buildMesh();
    var bog = new THREE.Group(bot)
    bog.add(bot)
    bog.position.z = -((w)/2);
    bog.position.y = -((w)/2);
    bog.rotation.x=(Math.PI/2)

    var g = new THREE.Group()
    g.add(fg)
    g.add(bg)
    g.add(lg)
    g.add(rg)
    g.add(tg)
    g.add(bog)
    
  scene.add(g)
    var sides = [
      ...fg.children,
      ...bg.children,
      ...rg.children,
      ...lg.children,
      ...tg.children,
      ...bog.children,
    ]

    var cnt = centerPosition(g)
    var localCenter = new THREE.Vector3();
    for (let index = 0; index < sides.length; index++) {
      const element = sides[index];
      let color = new THREE.Color( 0xffffff );
      color.setHex( Math.random() * 0xffffff );
      element.worldToLocal(localCenter.copy(cnt))
      element.material.uniforms['wTl'].value = localCenter
      element.material.uniforms['ps'].value = element.position
      element.material.uniforms['ucolor'].value = color

    }

  
  }


  function buildMesh(t){
    let geometry = new THREE.PlaneGeometry(w, w,50,50);
    uniforms = {
      ucolor:{value:new THREE.Vector3()}, 
      wTl:   {value:new THREE.Vector3()},
      ps:    {value:new THREE.Vector3()}
               }; 
    let material = new THREE.ShaderMaterial({
      uniforms: uniforms,
      fragmentShader: fragmentShader(),
      vertexShader: vertexShader(),
      wireframe:false
    });

    var mesh = new THREE.Mesh(geometry, material);
    return mesh
  }

  function centerPosition(g) {
    bbox.expandByObject(g);
    var center = new THREE.Vector3();
    bbox.getCenter(center);
    return center
  }

update()

function update(t) {
  renderer.render(scene, camera);
  requestAnimationFrame (update);
}
 <script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.js"></script> 

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

enter image description hereI ended up finding an answer. To obtain the center of a projected plane that is projected on the GPU, you need to take the position of the unprojected plane and project it.

function project( v, r, center ){
    v.sub( center ).setLength( r ).add( center );
} 

let positionCenter = new THREE.Vector3()
project(positionCenter,radiusOfSphere,centerOfSphere)

This will give you the center of the mesh then use plane.localToWorld(positionCenter) positionCenter.distanceTo(C) to get the correct distance.

The solution can be seen here: https://github.com/miguelmyers8/PlanetTechJS/blob/main/src/lib/PlanetTech/sphere/sphere.js

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .