Cannot pickPoint from the vertexData of this below

Hallo All,
i am creating a customScene by adding vertexData and adding it on a mesh…

after this, I like to pick the position of each vertex from this below scene and measure distance between the two points.

https://www.babylonjs-playground.com/#2S8L5U#35

Now using the above scene code, if I do this,
var vertexData = new BABYLON.VertexData();

    //calculate spiral conditions
    var finalAngle = 3.7 * Math.PI;
    var b = 0.23;
    var a = [];
    var l = rabbitPositions.length / 3;

    var colors = new Array(4 * l);
        colors = colors.fill(0).map((x) => {
        return Math.random();
    })

    //Create a custom mesh  
    var customMesh = new BABYLON.Mesh("custom", scene);

    //Assign positions
    vertexData.positions = rabbitPositions;
    vertexData.colors = colors;

    //Apply vertexData to custom mesh
    vertexData.applyToMesh(customMesh, true);

    var mat = new BABYLON.StandardMaterial("mat", scene);
    mat.emissiveColor = new BABYLON.Color3(1, 1, 1);
    //mat.disableLighting = true;
    mat.pointsCloud = true;
    mat.pointSize = 1;

    customMesh.material = mat;

        scene.onPointerDown = function (evt, pickResult) {
        if(evt.button != 0){
            return;
        }
        //left mouse click
        //pickedPoint the point you have clicked, transformed in 3D coordinates, depending on the object you’ve clicked. Null if no hit.
        if(evt.button == 0){
       console.log(pickResult);

}
this is what i get
e {_pickingUnavailable: false, hit: false, distance: 0, pickedPoint: null, pickedMesh: null, …}
bu: 0
bv: 0
distance: 0
faceId: -1
hit: false
originMesh: null
pickedMesh: null
pickedPoint: null
pickedSprite: null
ray: e {origin: e, direction: e, length: 1.7976931348623157e+308}
subMeshId: 0
_pickingUnavailable: false
proto: Object

instead of this pickingInfo : I want something like this below.
e {_pickingUnavailable: false, hit: true, distance: 23.237776793180558, pickedPoint: e, pickedMesh: t, …}
bu: 0.6707718003466827
bv: 0.19974599139453608
distance: 23.237776793180558
faceId: 9
hit: true
originMesh: null
pickedMesh: t {state: “”, metadata: null, reservedDataStore: null, _doNotSerialize: false, _isDisposed: false, …}
pickedPoint: e {x: -6.282334272636481, y: 2.600000000000005, z: -0.15226620307875116}
pickedSprite: null
ray: e {origin: e, direction: e, length: 1.7976931348623157e+308}
subMeshId: 0
_pickingUnavailable: false
proto: Object

Hey, do you mind sharing the repro which highlight the issue? I picked in your PG and I see there are hits so there must be something I not doing correctly to get the same issue as you

1 Like

Thank you for the response, i am trying to get distance between two pickedPoints. hit is not an issue in this playground i created, but i am not sure if we can use this to get distance.

can you share your code or playground with https://www.babylonjs-playground.com/#2S8L5U#35 that does the pickedPoint: {object hit}

When i used this above playground, i get pickedMesh as below not pickPoint… Can i used this to get the point x,y, z coordinates.

  1. bu: 0
  2. bv: 0
  3. distance: 193.08978515281527
  4. faceId: -1
  5. hit: true
  6. originMesh: null
  7. pickedMesh: t {state: “”, metadata: null, reservedDataStore: null, _doNotSerialize: false, _isDisposed: false, …}
  8. pickedPoint: null
  9. pickedSprite: null
  10. ray: e {origin: e, direction: e, length: 1.7976931348623157e+308}
  11. subMeshFaceId: -1
  12. subMeshId: -1
  13. thinInstanceIndex: -1
  14. _pickingUnavailable: false

ok gotcha! The mesh has no face so no pickedpoint per se
But you have the distance so the point is ray.origin + distance :slight_smile:

1 Like

Hallo Again, i am visiting this topic, as i hadplanned to check on this today.

Before i jump start, Can i ask if anyone can share a playground to pick distance between two points from ray.origin + distance , with this example https://www.babylonjs-playground.com/#2S8L5U#35

@Deltakosh Hallo David, could you help me with a playground, i tried to do this but i am getting errors

I like to have a solution that shows distance like this https://playground.babylonjs.com/#JIHTLS#1

when selecting two points from the 3d model here created using vertices,
https://www.babylonjs-playground.com/#2S8L5U#35

Sure but let’s start by fixing the error you get on your PG:)
image

1 Like

Hi David,
Good morning.
Thank you for your response, now can you guide me how to find distance fromo firstclick and secondClick pickedMesh using the solution ray.origin + distance.

Here is the updated link with what you can see in the console (attached)
https://www.babylonjs-playground.com/#2S8L5U#53

Here we are:
https://www.babylonjs-playground.com/#2S8L5U#56

You had a lot of undefined variables…

1 Like

Thank you, i appreciate it.

@Deltakosh: pickResult.hit is TRUE in babylon environment, however its FALSE When i convert this babylon code to a reactJS class component, I dont get the same results, the distance is wrong, as the points are not selected. can you see what is wrong with my code ?

import React, { Component } from ‘react’;
import * as BABYLON from ‘babylonjs’;
import {ArcRotateCamera, HemisphericLight, Vector3, MeshBuilder} from “@babylonjs/core”;
import BabylonScene from ‘./BabyLonScene’;
import axios from “axios”;

export default class Viewer extends Component<{}, {}> {
state = {
termUrl: ‘https://cdn.jsdelivr.net/gh/BabylonJSGuide/oddsNEdnds@86e4f9e4faf9c5f47232ebac12ad0b6d7509e5bf/dudeRabbit.js’,
scanData: ,
error: null,
data: null

}

constructor(props) {
    super(props);
    this.state = {
        list: [],
        termUrl : this.state.termUrl,
        scanData: [],
        data: null
    };
}

componentDidMount() {
    const that = this;
    axios.get(this.state.termUrl)
        .then((response) => {
            this.setState({list: response.data});
            //console.log("what is fetched: " + this.state.list);
            //console.log("newDAta"+ newData);
            const arrayData = this.get3DArray(response.data);
            that.setState({
                scanData: this.state.list,
                data: arrayData
            }, () => {
                console.log('data in state', this.state.data)
            });
        })
        .catch((error) => {
            console.log("FAILED", error);
        });
}

meshPicked(mesh) {
    console.log('mesh picked:', mesh)
}

get3DArray = (data) => {
    var positions = [];
    positions = data;
    return positions;
}


onSceneMount = (e: SceneEventArgs) => {

    // This creates a basic Babylon Scene object (non-mesh)
    let {canvas, engine} = e;
    let scene = new BABYLON.Scene(this.engine);
    this.scene = scene;
    // Scene to build your environment, Canvas you need to attach your camera.
    var camera = new ArcRotateCamera("Camera", 3 * Math.PI / 2, Math.PI / 8, 15, BABYLON.Vector3.Zero(), scene);
    camera.attachControl(canvas)
    var customMesh = new BABYLON.Mesh("custom", scene);

    new HemisphericLight('light', Vector3.Up(), scene);
    //MeshBuilder.CreateBox('box', {size: 3}, scene)
    /* Some preparation */
    const dArray = this.get3DArray();
    var newData = [];
    newData = this.state.data.replace(/(^.*\[|\].*$)/g, '');
    var b = newData.split`,`.map(x => +x);
    var arr = "[" + newData + "]";

    //Assign positions to vertex, morphing feature
    var dudePositions = b;
    console.log("These are my " + dudePositions);
    var vertexData = new BABYLON.VertexData();
    vertexData.positions = dudePositions;
    //if length not divided, the screen freezes
    if (arr) {
        var l = arr.length / 3;
        //console.log("length is "+ l);
    } else {
        var l = null;
    }
    var colors = new Array(4 * l);
    colors = colors.fill(0).map((x) => {
        return Math.random();
    })
    vertexData.colors = colors;
    //Apply vertexData to custom mesh
    vertexData.applyToMesh(customMesh, true);

    var mat = new BABYLON.StandardMaterial("mat", scene);
    mat.emissiveColor = new BABYLON.Color3(1, 1, 1);
    mat.pointsCloud = true;
    mat.pointSize = 2;
    customMesh.material = mat;

    //mark two points on the Vector3
    var firstClick = true;
    let firstClickPosition;
    let secondClickPosition;

    //render the uncompressed points.

    var firstClickPos = null;
    // Ball impostor or create a point
    var ball = BABYLON.Mesh.CreateSphere("sphere", 2, 0.5, scene);
    ball.isPickable = false;
    var tempx = ball.position.x;
    console.log("tempx:", tempx);
    var temp = ball.position;
    console.log("temp:", temp);

    //rendering the scene.
    scene.getEngine().runRenderLoop(() => {
        if (scene) {
            scene.render();
        }
    });

    //pointer events
    scene.onPointerDown = function (evt, pickResult) {
        var pickResult = scene.pick(scene.pointerX, scene.pointerY);

        console.log(pickInfo.hit); //always gives false.
        if (pickInfo.hit) {
            if (firstClick) {
                firstClickPosition = pickResult.ray.origin.add(pickResult.ray.direction.scale(pickResult.distance));
                console.log("first click done and false:  " + firstClickPosition);

                //overwrite the existing ball point position to selected pickPoint on a mesh
                ball.position = firstClickPosition;
                temp = ball.position;
                tempx = ball.position.x;
                firstClick = false;


            } else if (!firstClick) {
                console.log("must be second click, first click is :  " + firstClick);
                console.log("Read the second point and calculate distance");
                console.log("Distance formula ");
                secondClickPosition = pickResult.ray.origin.add(pickResult.ray.direction.scale(pickResult.distance));
                console.log(secondClickPosition)

                //add a second point location for marking.
                ball.position = secondClickPosition;
                console.log(BABYLON.Vector3.Distance(secondClickPosition, firstClickPosition));
                var diff = BABYLON.Vector3.Distance(secondClickPosition, firstClickPosition); 
                //show distance in axis
                firstClick = true;
                showAxis(temp, ball.position, diff.toPrecision(2));

            }
        }
    };
    
    //show the distance line on a plane.
    var showAxis = function (previous, current, size) {
        const styles = {
            alpha: 1,
            backgroundColor: "white",
            borderColor: "white",
            color: "black",
            fontFamily: "Arial",
            fontSize: 16,
            fontWeight: "300",
            height: 30,
            hoverCursor: "pointer",
            width: 30,
        };

        var makeTextPlane = function (text, color, size) {
            // GUI
            color = "white";
            var dynamicTexture = new BABYLON.DynamicTexture("DynamicTexture", 50, scene, true);
            dynamicTexture.hasAlpha = true;
            //dynamicTexture.drawText(text, 5, 60, "bold 36px Arial", color , "transparent", true);
            var plane = new BABYLON.Mesh.CreatePlane("TextPlane", size, scene, true);

            return plane;
        };

        var axisX = BABYLON.Mesh.CreateLines("axisX", [
            previous, current], scene);
        axisX.color = new BABYLON.Color3(5, 0, 0);

    };

    engine.runRenderLoop(() => {
        if (scene) {
            scene.render();
        }

    });
}

render(){
    // if your API call hasn't finished
    if (!this.state.data || !this.state.scanData) {
        return null
    }
    return (
        <BabylonScene onSceneMount={this.onSceneMount}/>
        )
}

}

Unfortunately it is complicated to help with a dump of your code :frowning:
But as you stated there is obviously a difference

I would recommend to check the values of scene.pointerX, scene.pointerY for instance

1 Like

Also make sure your meshes are isPickable = true

The scene is same, I tried to recreate the scene https://www.babylonjs-playground.com/#2S8L5U#56 in ReactJS, i dont know how i can create this in playground. if any one can have a look, it would be highly appreciated

pinging @brianzinn just in case :slight_smile:

Do you need to do scene.pick? Why not just add an observable like this:

 const pointerDownObservable: Nullable<Observer<PointerInfo>> = scene.onPointerObservable.add(
      (evt: PointerInfo) => {

        if (evt && evt.pickInfo && evt.pickInfo.hit && evt.pickInfo.pickedMesh) {
          let mesh = evt.pickInfo.pickedMesh;
          // this mesh has been picked
        }
      },
      PointerEventTypes.POINTERDOWN
    );

I’ve scene pointerX and pointerY values being off even without react. What are your pointerX and pointerY - you should be able to work backwards from the screen coordinates maybe subtracting top or left properties or maybe I needed to scale to canvas width/height - can’t recall exactly how I got stuck there before.

ps: @Deltakosh click on “Find playground examples here” - my internet search took me to the chinese version, but find on playground looks broken: Scene - Babylon.js Documentation

@Deltakosh still not working, i did ispickable to true.

@brianzinn You were trying to share this link, Playground search page | Babylon.js Documentation

No, I meant to share the link that looked broken.

Are you saying that the code that I provided did not work? Or why do you need to use scene.pointerX - can you report on what those values are in relation to your canvas size? I’ve had trouble in the past and you can see when you pick the corners - I believe it was due to css or pixel ratio.

You mean, var result = scene.pick(scene.pointerX, scene.pointerY, null, null, camera); ?? i dont need this values, i was looking to use pickResult from scene.onPointerDown = function (evt, pickResult) {}

no, I mean does the pointer look correct based on your canvas size? I don’t know if I am sending you down the right path, but if you scene pick isn’t working then you are sending the wrong screen coordinates, which would explain why your pointer down doesn’t work.

...
console.log(window.devicePixelRatio);
console.log(`scene pointer at ${scene.pointerX},${scene.pointerY}`);
scene.pick(....);