tentone / potree-core

Potree point cloud viewer library core components for easier integration in a three.js project.
https://tentone.github.io/potree-core/
Other
178 stars 57 forks source link

attributes.position.array is missing #39

Closed nachoSource closed 5 months ago

nachoSource commented 5 months ago

I am trying to find the attributes.position.array of my pointcloud, present in pointclouds when rendered after using PotreeConverter. My final goal is to get its center in order to move it around. To be more specific, centering with position.set(0,0,0) is not enough for every model so I figured out how to move it using each point's position so I need that array. Instead, a ranged structure is being returned but I am not sure if I can still use it for my purpose.

pco.pcoGeometry.pointAttributes.attributes:

Screenshot 2024-04-19 at 15 25 08

This code is based on the example that we have in the README file:

  const loadPointCloud = async (url, position = null, rotation = null, scale = null) => {
    const pco = await potree.loadPointCloud(url, (url) => `${url}.laz`);

    // TODO check these
    pco.material.size = 1.0;
    pco.material.shape = 2;
    pco.material.inputColorEncoding = 1;
    pco.material.outputColorEncoding = 1;

    if (position) {
      pco.position.copy(position);
    }
    if (rotation) {
      pco.rotation.copy(rotation);
    }
    if (scale) {
      pco.scale.copy(scale);
    }

    console.log("Pointcloud file loaded", pco);
    pco.showBoundingBox = false;

    addPointCloud(pco);

    console.log(pco.geometry) // undefined
    console.log(pco.attributes) // undefined
    console.log(pco.pcoGeometry.attributes) // undefined
    console.log(pco.root.geometry) // null
    console.log(pco.root.attributes) // undefined

    const center = getCenter(pco.children[0].geometry.attributes.position.array);

    pco.position.sub(new Vector3(center.x, center.y, center.z));
  };

The following code is mine and is used to generate a model true center that truly reflects an average of every point's position.

const getCenter = (posArray) => {
  const posChunks = getPosChunks(posArray);
  let acumX = 0;
  let acumY = 0;
  let acumZ = 0;

  posChunks.forEach((ch) => {
    acumX += ch[0];
    acumY += ch[1];
    acumZ += ch[2];
  });

  const center = {
    x: acumX / posChunks.length,
    y: acumY / posChunks.length,
    z: acumZ / posChunks.length
  };

  console.log("center", center);
  return center;
};

const getPosChunks = (positions) => {
  const chunkSize = 3;
  const positionChunks = [];
  for (let i = 0; i < positions.length; i += chunkSize) {
    const chunk = positions.slice(i, i + chunkSize);
    positionChunks.push(chunk);
  }

  return positionChunks;
};

export { getCenter, getPosChunks };

Finally, I am able to move it to origin with this line:

pco.position.set(-center.x, -center.y, -center.z);

or even create another pointcloud from a centered set of points:

    const center = getCenter(points.geometry.attributes.position.array);

    // model is being transported to Origin since it gets difficult
    // to manipulate when too far from it
    centeredPoints = points.map(({ x, y, z }) =>
            new THREE.Vector3(x, y, z).sub(center)
    );

Any ideas of where can I find this positions array? If not possible, does someone know how to properly get a pointcloud center's position without accessing every point coordinates as I am trying to do?

nachoSource commented 5 months ago

Here you have my package.json in case you need it

{
  "name": "react-webgl",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview"
  },
  "dependencies": {
    "-": "^0.0.1",
    "@react-three/drei": "^9.102.6",
    "@react-three/fiber": "^8.15.19",
    "@reduxjs/toolkit": "^2.2.3",
    "@types/three": "^0.162.0",
    "jquery": "^3.7.1",
    "leva": "^0.9.35",
    "localforage": "^1.10.0",
    "match-sorter": "^6.3.4",
    "potree-core": "^2.0.7",
    "potree-loader": "^1.10.4",
    "proj4": "^2.10.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-redux": "^9.1.1",
    "react-router-dom": "^6.22.3",
    "save-dev": "^0.0.1-security",
    "sort-by": "^1.2.0",
    "three": "^0.160.1",
    "vite-plugin-commonjs": "^0.10.1",
    "wkt-parser": "^1.3.3"
  },
  "devDependencies": {
    "@types/react": "^18.2.64",
    "@types/react-dom": "^18.2.21",
    "@vitejs/plugin-react": "^4.2.1",
    "eslint": "^8.57.0",
    "eslint-config-prettier": "^9.1.0",
    "eslint-plugin-prettier": "^5.1.3",
    "eslint-plugin-react": "^7.34.1",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.5",
    "prettier": "^3.2.5",
    "ts-loader": "^9.5.1",
    "vite": "^5.1.6"
  }
}
nachoSource commented 5 months ago

I solved it out! The old-structured pointcloud was inside its own children. Now I can get a Points object and work with every point's position

console.log(pco)

Screenshot 2024-04-22 at 16 55 13