From 1b4e0fa5c57653be748f15b331c33bd7bed30f26 Mon Sep 17 00:00:00 2001 From: Matthew Tancik Date: Sun, 11 Sep 2022 12:05:51 -0700 Subject: [PATCH] Switch to using meshline (#393) --- nerfactory/viewer/app/package.json | 1 + .../SidePanel/CameraPanel/CameraHelper.js | 142 ++++++++++++++++++ .../SidePanel/CameraPanel/CameraPanel.jsx | 14 +- nerfactory/viewer/app/yarn.lock | 5 + 4 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 nerfactory/viewer/app/src/modules/SidePanel/CameraPanel/CameraHelper.js diff --git a/nerfactory/viewer/app/package.json b/nerfactory/viewer/app/package.json index a5b070339..8456f9c71 100644 --- a/nerfactory/viewer/app/package.json +++ b/nerfactory/viewer/app/package.json @@ -21,6 +21,7 @@ "eslint-config-prettier": "^8.5.0", "eslint-plugin-unused-imports": "^2.0.0", "leva": "^0.9.29", + "meshline": "^2.0.4", "msgpack-lite": "^0.1.26", "prop-types": "^15.8.1", "re-resizable": "^6.9.9", diff --git a/nerfactory/viewer/app/src/modules/SidePanel/CameraPanel/CameraHelper.js b/nerfactory/viewer/app/src/modules/SidePanel/CameraPanel/CameraHelper.js new file mode 100644 index 000000000..7a3d3cb55 --- /dev/null +++ b/nerfactory/viewer/app/src/modules/SidePanel/CameraPanel/CameraHelper.js @@ -0,0 +1,142 @@ +import * as THREE from 'three'; +import { MeshLine, MeshLineMaterial } from 'meshline'; + +// eslint-disable-next-line no-underscore-dangle +const _vector = new THREE.Vector3(); +// eslint-disable-next-line no-underscore-dangle +const _camera = new THREE.Camera(); + +function setPoint(point, pointMap, geometry, camera, x, y, z) { + _vector.set(x, y, z).unproject(camera); + + const points = pointMap[point]; + + if (points !== undefined) { + const position = geometry.getAttribute('position'); + + for (let i = 0, l = points.length; i < l; i += 1) { + position.setXYZ(points[i], _vector.x, _vector.y, _vector.z); + } + } +} + +/** + * - Modified version of THREE.CameraHelper + */ + +class CameraHelper extends THREE.Mesh { + constructor(camera) { + const line_geometry = new THREE.BufferGeometry(); + const geometry = new THREE.BufferGeometry(); + const material = new MeshLineMaterial({ + color: 0x000000, + lineWidth: 0.04, + }); + + const vertices = []; + + const pointMap = {}; + + function addPoint(id) { + vertices.push(0, 0, 0); + + if (pointMap[id] === undefined) { + pointMap[id] = []; + } + + pointMap[id].push(vertices.length / 3 - 1); + } + + function addLine(a, b) { + addPoint(a); + addPoint(b); + } + + // near + + addLine('n1', 'n2'); + addLine('n2', 'n4'); + addLine('n4', 'n3'); + addLine('n3', 'n1'); + + // cone + + addLine('p', 'n1'); + addLine('p', 'n2'); + addLine('p', 'n3'); + addLine('p', 'n4'); + + // up + + addLine('u1', 'u2'); + addLine('u2', 'u3'); + addLine('u3', 'u1'); + + line_geometry.setAttribute( + 'position', + new THREE.Float32BufferAttribute(vertices, 3), + ); + + super(geometry, material); + + this.type = 'CameraHelper'; + + this.camera = camera; + if (this.camera.updateProjectionMatrix) + this.camera.updateProjectionMatrix(); + + this.matrix = camera.matrixWorld; + this.matrixAutoUpdate = false; + + this.pointMap = pointMap; + + this.line_geometry = line_geometry; + + this.update(); + } + + update() { + const geometry = this.line_geometry; + const pointMap = this.pointMap; + + const w = 1; + const h = 1; + const z = 2; + + // we need just camera projection matrix inverse + // world matrix must be identity + + _camera.projectionMatrixInverse.copy(this.camera.projectionMatrixInverse); + + // center + + setPoint('c', pointMap, geometry, _camera, 0, 0, -1); + setPoint('t', pointMap, geometry, _camera, 0, 0, 1); + + // near + + setPoint('n1', pointMap, geometry, _camera, -w, -h, z); + setPoint('n2', pointMap, geometry, _camera, w, -h, z); + setPoint('n3', pointMap, geometry, _camera, -w, h, z); + setPoint('n4', pointMap, geometry, _camera, w, h, z); + + // up + + setPoint('u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, z); + setPoint('u2', pointMap, geometry, _camera, -w * 0.7, h * 1.1, z); + setPoint('u3', pointMap, geometry, _camera, 0, h * 2, z); + + geometry.getAttribute('position').needsUpdate = true; + + const camera_vis = new MeshLine(); + camera_vis.setGeometry(geometry); + this.geometry = camera_vis.geometry; + } + + dispose() { + this.geometry.dispose(); + this.material.dispose(); + } +} + +export { CameraHelper }; diff --git a/nerfactory/viewer/app/src/modules/SidePanel/CameraPanel/CameraPanel.jsx b/nerfactory/viewer/app/src/modules/SidePanel/CameraPanel/CameraPanel.jsx index 7e92b2399..824d93ab0 100644 --- a/nerfactory/viewer/app/src/modules/SidePanel/CameraPanel/CameraPanel.jsx +++ b/nerfactory/viewer/app/src/modules/SidePanel/CameraPanel/CameraPanel.jsx @@ -1,5 +1,6 @@ import * as React from 'react'; import * as THREE from 'three'; +import { MeshLine, MeshLineMaterial } from 'meshline'; import { Button, Slider } from '@mui/material'; @@ -13,6 +14,7 @@ import PlayArrowIcon from '@mui/icons-material/PlayArrow'; import TextField from '@mui/material/TextField'; import VisibilityIcon from '@mui/icons-material/Visibility'; import { useEffect } from 'react'; +import { CameraHelper } from './CameraHelper'; import { get_curve_object_from_cameras } from './curve'; function set_camera_position(camera, matrix) { @@ -119,7 +121,9 @@ export default function CameraPanel(props) { sceneTree.delete(['Camera Path', 'Cameras']); // delete old cameras, which is important for (let i = 0; i < cameras.length; i += 1) { const camera = cameras[i]; - const helper = new THREE.CameraHelper(camera); + const helper = new CameraHelper(camera); + console.log('HERERE'); + console.log(helper); // camera sceneTree.set_object_from_path( ['Camera Path', 'Cameras', i.toString(), 'Camera'], @@ -139,9 +143,11 @@ export default function CameraPanel(props) { const num_points = fps * seconds; const points = curve_object.curve_positions.getPoints(num_points); const geometry = new THREE.BufferGeometry().setFromPoints(points); - const material = new THREE.LineBasicMaterial({ color: 0xff0000 }); - const threejs_object = new THREE.Line(geometry, material); - sceneTree.set_object_from_path(['Camera Path', 'Curve'], threejs_object); + const spline = new MeshLine(); + spline.setGeometry(geometry); + const material = new MeshLineMaterial({ lineWidth: 0.05, color: 0xff5024 }); + const spline_mesh = new THREE.Mesh(spline.geometry, material); + sceneTree.set_object_from_path(['Camera Path', 'Curve'], spline_mesh); } const marks = []; diff --git a/nerfactory/viewer/app/yarn.lock b/nerfactory/viewer/app/yarn.lock index d5d5d5529..0bb97c74f 100644 --- a/nerfactory/viewer/app/yarn.lock +++ b/nerfactory/viewer/app/yarn.lock @@ -6868,6 +6868,11 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +meshline@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/meshline/-/meshline-2.0.4.tgz#39c7bcf36b503397642f2312e6211f2a8ecf75c5" + integrity sha512-Jh6DJl/zLqA4xsKvGv5950jr2ukyXQE1wgxs8u94cImHrvL6soVIggqjP+2hVHZXGYaKnWszhtjuCbKNeQyYiw== + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"