mirror of
https://github.com/nerfstudio-project/nerfstudio.git
synced 2026-11-11 02:24:38 +08:00
additional viewer features (#532)
* added catmul close cycle * removed lock files added smoothing in camera * maybe lock files are necessary? * check versioning * revert yarn lock
This commit is contained in:
parent
840bac9fc7
commit
fa9c775fe6
31639
nerfactory/viewer/app/package-lock.json
generated
31639
nerfactory/viewer/app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -9,6 +9,7 @@
|
||||
"@mui/icons-material": "^5.10.3",
|
||||
"@mui/lab": "^5.0.0-alpha.98",
|
||||
"@mui/material": "^5.10.3",
|
||||
"@mui/system": "^5.10.6",
|
||||
"@mui/x-date-pickers": "^5.0.0",
|
||||
"@reduxjs/toolkit": "^1.8.3",
|
||||
"@testing-library/jest-dom": "^5.16.4",
|
||||
|
||||
@ -19,6 +19,8 @@ import TextField from '@mui/material/TextField';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import VisibilityIcon from '@mui/icons-material/Visibility';
|
||||
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer';
|
||||
import { Stack } from '@mui/system';
|
||||
import { AllInclusiveOutlined, ChangeHistory, GestureOutlined, RadioButtonUnchecked, Replay } from '@mui/icons-material';
|
||||
import { CameraHelper } from './CameraHelper';
|
||||
import { get_curve_object_from_cameras, get_transform_matrix } from './curve';
|
||||
import { WebSocketContext } from '../../WebSocket/WebSocket';
|
||||
@ -53,6 +55,7 @@ function CameraList(props) {
|
||||
'ViewerWindow-buttons',
|
||||
)[0];
|
||||
if (camera === transform_controls.object) {
|
||||
// double click to remove controls from object
|
||||
transform_controls.detach();
|
||||
viewer_buttons.style.display = 'none';
|
||||
} else {
|
||||
@ -92,8 +95,8 @@ function CameraList(props) {
|
||||
}
|
||||
set_camera_position(camera_render, first_camera.matrix);
|
||||
camera_render_helper.set_visibility(true);
|
||||
set_slider_value(slider_min);
|
||||
}
|
||||
set_slider_value(slider_min);
|
||||
};
|
||||
|
||||
const delete_camera = (index) => {
|
||||
@ -132,7 +135,9 @@ function CameraList(props) {
|
||||
</Button>
|
||||
<div className="CameraList-row-buttons">
|
||||
<Button
|
||||
onClick={() => set_camera_position(camera_main, camera.matrix)}
|
||||
onClick={() => {
|
||||
set_camera_position(camera_main, camera.matrix);
|
||||
}}
|
||||
>
|
||||
<VisibilityIcon />
|
||||
</Button>
|
||||
@ -175,7 +180,9 @@ export default function CameraPanel(props) {
|
||||
// react state
|
||||
const [cameras, setCameras] = React.useState([]);
|
||||
const [slider_value, set_slider_value] = React.useState(0);
|
||||
const [smoothness_value, set_smoothness_value] = React.useState(0.5);
|
||||
const [is_playing, setIsPlaying] = React.useState(false);
|
||||
const [is_cycle, setIsCycle] = React.useState(false);
|
||||
const [seconds, setSeconds] = React.useState(4);
|
||||
const [fps, setFps] = React.useState(24);
|
||||
|
||||
@ -296,7 +303,7 @@ export default function CameraPanel(props) {
|
||||
}, [cameras, render_width, render_height]);
|
||||
|
||||
// update the camera curve
|
||||
const curve_object = get_curve_object_from_cameras(cameras);
|
||||
const curve_object = get_curve_object_from_cameras(cameras, is_cycle, smoothness_value);
|
||||
|
||||
if (cameras.length > 1) {
|
||||
const num_points = fps * seconds;
|
||||
@ -366,6 +373,7 @@ export default function CameraPanel(props) {
|
||||
}
|
||||
}, [slider_value]);
|
||||
|
||||
|
||||
const get_camera_path = () => {
|
||||
// NOTE: currently assuming these are ints
|
||||
const num_points = fps * seconds;
|
||||
@ -479,6 +487,29 @@ export default function CameraPanel(props) {
|
||||
Export Path
|
||||
</Button>
|
||||
</div>
|
||||
<div className="CameraPanel-top-button">
|
||||
<Tooltip title="Close/open camera curve">
|
||||
{!is_cycle ? (
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={() => {
|
||||
setIsCycle(true);
|
||||
}}
|
||||
>
|
||||
<GestureOutlined />
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={() => {
|
||||
setIsCycle(false);
|
||||
}}
|
||||
>
|
||||
<AllInclusiveOutlined />
|
||||
</Button>
|
||||
)}
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="CameraPanel-top-button">
|
||||
<Tooltip title="Copy Cmd to Clipboard">
|
||||
<IconButton onClick={copy_cmd_to_clipboard}>
|
||||
@ -486,6 +517,24 @@ export default function CameraPanel(props) {
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="CameraPanel-slider-container">
|
||||
|
||||
<Stack spacing={2} direction="row" sx={{ mb: 1 }} alignItems="center">
|
||||
<p style={{ fontSize: "smaller", color: "#999999"}}>Smoothness</p>
|
||||
<ChangeHistory />
|
||||
<Slider
|
||||
value={smoothness_value}
|
||||
step={step_size}
|
||||
valueLabelFormat={smoothness_value.toFixed(2)}
|
||||
min={0}
|
||||
max={1}
|
||||
onChange={(event, value) => {
|
||||
set_smoothness_value(value);
|
||||
}}
|
||||
/>
|
||||
<RadioButtonUnchecked />
|
||||
</Stack>
|
||||
</div>
|
||||
<div className="CameraPanel-slider-container">
|
||||
<Slider
|
||||
value={slider_value}
|
||||
@ -517,27 +566,36 @@ export default function CameraPanel(props) {
|
||||
>
|
||||
<ArrowBackIosNewIcon />
|
||||
</Button>
|
||||
|
||||
{!is_playing ? (
|
||||
{/* eslint-disable-next-line no-nested-ternary */}
|
||||
{!is_playing && slider_max === slider_value ? (
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={() => {
|
||||
if (cameras.length > 1) {
|
||||
setIsPlaying(true);
|
||||
}
|
||||
set_slider_value(slider_min);
|
||||
}}
|
||||
>
|
||||
<PlayArrowIcon />
|
||||
<Replay />
|
||||
</Button>
|
||||
) : (
|
||||
!is_playing ? (
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={() => {
|
||||
if (cameras.length > 1) {
|
||||
setIsPlaying(true);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<PlayArrowIcon />
|
||||
</Button> ) :
|
||||
(<Button
|
||||
variant="outlined"
|
||||
onClick={() => {
|
||||
setIsPlaying(false);
|
||||
}}
|
||||
>
|
||||
<PauseIcon />
|
||||
</Button>
|
||||
}}
|
||||
>
|
||||
<PauseIcon />
|
||||
</Button> )
|
||||
)}
|
||||
<Button
|
||||
variant="outlined"
|
||||
|
||||
@ -2,18 +2,19 @@
|
||||
|
||||
import * as THREE from 'three';
|
||||
|
||||
function get_curve(list_of_3d_vectors) {
|
||||
function get_curve(list_of_3d_vectors, is_cycle, smoothness_value) {
|
||||
// TODO: add some hyperparameters to this function
|
||||
const curve = new THREE.CatmullRomCurve3(
|
||||
list_of_3d_vectors,
|
||||
false,
|
||||
is_cycle,
|
||||
// 'centripetal'
|
||||
'chordal',
|
||||
'catmullrom',
|
||||
smoothness_value,
|
||||
);
|
||||
return curve;
|
||||
}
|
||||
|
||||
export function get_curve_object_from_cameras(cameras) {
|
||||
export function get_curve_object_from_cameras(cameras, is_cycle, smoothness_value) {
|
||||
// interpolate positions, lookat directions, and ups
|
||||
// similar to
|
||||
// https://github.com/google-research/multinerf/blob/1c8b1c552133cdb2de1c1f3c871b2813f6662265/internal/camera_utils.py#L281
|
||||
@ -40,9 +41,9 @@ export function get_curve_object_from_cameras(cameras) {
|
||||
let curve_lookats = null;
|
||||
let curve_ups = null;
|
||||
|
||||
curve_positions = get_curve(positions);
|
||||
curve_lookats = get_curve(lookats);
|
||||
curve_ups = get_curve(ups);
|
||||
curve_positions = get_curve(positions, is_cycle, smoothness_value);
|
||||
curve_lookats = get_curve(lookats, is_cycle, smoothness_value);
|
||||
curve_ups = get_curve(ups, is_cycle, smoothness_value);
|
||||
|
||||
const curve_object = {
|
||||
curve_positions,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user