layered geometries
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
.overlay-panels {
|
||||
z-index: 15000;
|
||||
z-index: 9000;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
@@ -5,48 +5,31 @@ import { observer } from 'mobx-react-lite';
|
||||
import { state } from '../state';
|
||||
import { SceneView } from './SceneView';
|
||||
import { MOUSE, type OrthographicCamera, type PerspectiveCamera } from 'three';
|
||||
import { CameraSync } from './tools/CameraSync';
|
||||
import { useSyncCamera } from '../utils/hooks/useSyncCamera';
|
||||
import { Physics } from '@react-three/rapier';
|
||||
|
||||
|
||||
export const SceneEditorView = observer(function () {
|
||||
const controlsRef = useRef<React.ComponentRef<typeof OrbitControls>>(null);
|
||||
|
||||
const cameraAtStart = useRef<string>('');
|
||||
|
||||
function cameraSnapshot(camera: OrthographicCamera | PerspectiveCamera): string {
|
||||
return JSON.stringify({
|
||||
position: camera.position,
|
||||
rotation: camera.rotation,
|
||||
});
|
||||
}
|
||||
|
||||
const handleStart = () => {
|
||||
const controls = controlsRef.current;
|
||||
if (!controls)
|
||||
return;
|
||||
cameraAtStart.current = cameraSnapshot(controls.object);
|
||||
};
|
||||
useSyncCamera(() => state.view.camera.camera);
|
||||
|
||||
const handleEnd = () => {
|
||||
const controls = controlsRef.current;
|
||||
if (!controls)
|
||||
return;
|
||||
const snapshot = cameraSnapshot(controls.object);
|
||||
if (snapshot === cameraAtStart.current)
|
||||
return;
|
||||
|
||||
const [x, y, z] = controls.object.rotation.toArray();
|
||||
state.worldEditor.setCamera({
|
||||
state.view.camera.camera = {
|
||||
position: controls.object.position.toArray(),
|
||||
look: [x, y, z],
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
return (<>
|
||||
<Suspense>
|
||||
<OrbitControls
|
||||
ref={controlsRef}
|
||||
onStart={handleStart}
|
||||
onEnd={handleEnd}
|
||||
makeDefault
|
||||
mouseButtons={{
|
||||
@@ -57,7 +40,6 @@ export const SceneEditorView = observer(function () {
|
||||
rotateSpeed={0.2}
|
||||
enableDamping={false}
|
||||
/>
|
||||
<CameraSync camera={state.worldEditor.camera} />
|
||||
{/* <Grid
|
||||
sectionThickness={0.5}
|
||||
cellThickness={0}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
import { useFrame } from "@react-three/fiber";
|
||||
import type { Pos3 } from "../../types";
|
||||
import { Euler, Quaternion, Vector3 } from "three";
|
||||
|
||||
const _q = new Quaternion();
|
||||
const _e = new Euler(0, 0, 0, 'YXZ');
|
||||
const _offset = new Vector3();
|
||||
const _charPos = new Vector3();
|
||||
const _lookAt = new Vector3();
|
||||
|
||||
type Props = {
|
||||
camera: Pos3;
|
||||
};
|
||||
|
||||
export function CameraLayer({ camera: cameraPos }: Props) {
|
||||
|
||||
useFrame(({ camera }) => {
|
||||
// const t = rb.translation();
|
||||
// _charPos.set(t.x, t.y, t.z);
|
||||
// _offset.copy(shoulderOffset).applyEuler(_e.set(pitchRef.current, yawRef.current, 0, 'YXZ'));
|
||||
// camera.position.copy(_charPos).add(_offset);
|
||||
// _lookAt.set(t.x, t.y + lookAtY, t.z);
|
||||
camera.lookAt(_lookAt);
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -1,23 +1,19 @@
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { ObjectGeometriesLayer } from "./ObjectGeometriesLayer";
|
||||
import { Canvas } from "@react-three/fiber";
|
||||
import { Perf } from "r3f-perf";
|
||||
import { state } from "../../state";
|
||||
import { CameraLayer } from "./GameraLayer";
|
||||
import { SceneEditorCameraLayer } from "./SceneEditorGameraLayer";
|
||||
import { LightsLayer } from "./LighsLayer";
|
||||
import { StatsLayer } from './StatsLayer';
|
||||
|
||||
export const LayeredThreeView = observer(function () {
|
||||
|
||||
return <>
|
||||
<Canvas
|
||||
// camera={state.world.character.camera}
|
||||
>
|
||||
<ambientLight intensity={0.5} />
|
||||
<directionalLight position={[5, 5, 5]} intensity={1} />
|
||||
|
||||
<Perf position="bottom-right" />
|
||||
|
||||
<CameraLayer camera={state.worldEditor.camera} />
|
||||
<Canvas>
|
||||
<LightsLayer />
|
||||
{/* <Perf position="bottom-right" /> */}
|
||||
<SceneEditorCameraLayer />
|
||||
<ObjectGeometriesLayer />
|
||||
<StatsLayer />
|
||||
</Canvas>
|
||||
</>;
|
||||
});
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
export const LightsLayer = observer(function () {
|
||||
return <>
|
||||
<ambientLight intensity={0.5} />
|
||||
<directionalLight position={[5, 5, 5]} intensity={1} />
|
||||
</>;
|
||||
});
|
||||
@@ -1,8 +1,9 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useThree, useFrame } from "@react-three/fiber";
|
||||
import { useThree } from "@react-three/fiber";
|
||||
import { ObjectGeometryList } from "../../rendering/ObjectGeometryList";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { state } from "../../state";
|
||||
import { useLayerFrame } from "../../utils/hooks/useLayerFrame";
|
||||
|
||||
export const ObjectGeometriesLayer = observer(function () {
|
||||
|
||||
@@ -20,7 +21,7 @@ export const ObjectGeometriesLayer = observer(function () {
|
||||
};
|
||||
}, [threeScene, geometries]);
|
||||
|
||||
useFrame(() => list.current?.tick());
|
||||
useLayerFrame("ObjectGeometries", () => list.current?.tick());
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { OrbitControls } from "@react-three/drei";
|
||||
import { state } from "../../state";
|
||||
import { useRef } from "react";
|
||||
import { useSyncCamera } from "../../utils/hooks/useSyncCamera";
|
||||
import { MOUSE } from "three";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import type { V3 } from "../../types";
|
||||
|
||||
export const SceneEditorCameraLayer = observer(function () {
|
||||
const controlsRef = useRef<React.ComponentRef<typeof OrbitControls>>(null);
|
||||
|
||||
useSyncCamera(() => state.view.camera?.camera);
|
||||
|
||||
const handleEnd = () => {
|
||||
const controls = controlsRef.current;
|
||||
const camera = state.view.camera;
|
||||
if (!controls || !camera)
|
||||
return;
|
||||
|
||||
camera.camera = {
|
||||
position: controls.object.position.toArray(),
|
||||
look: controls.object.rotation.toArray().slice(0, 3) as V3,
|
||||
};
|
||||
};
|
||||
|
||||
if (!state.view.camera)
|
||||
return null;
|
||||
|
||||
return <OrbitControls
|
||||
ref={controlsRef}
|
||||
onEnd={handleEnd}
|
||||
makeDefault
|
||||
mouseButtons={{
|
||||
LEFT: MOUSE.ROTATE,
|
||||
MIDDLE: MOUSE.PAN,
|
||||
RIGHT: MOUSE.PAN,
|
||||
}}
|
||||
rotateSpeed={0.2}
|
||||
enableDamping={false}
|
||||
/>;
|
||||
});
|
||||
@@ -0,0 +1,71 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useFrame } from "@react-three/fiber";
|
||||
import { layerTimings } from "../../utils/layerTimings";
|
||||
|
||||
export const StatsLayer = function () {
|
||||
const divRef = useRef<HTMLDivElement | null>(null);
|
||||
const fpsFrames = useRef(0);
|
||||
const fpsLastTime = useRef(0);
|
||||
const renderAcc = useRef(0);
|
||||
|
||||
useEffect(() => {
|
||||
fpsLastTime.current = performance.now();
|
||||
|
||||
const div = document.createElement("div");
|
||||
Object.assign(div.style, {
|
||||
position: "absolute",
|
||||
bottom: "8px",
|
||||
right: "8px",
|
||||
color: "#0f0",
|
||||
fontSize: "14px",
|
||||
fontFamily: "monospace",
|
||||
zIndex: "9999",
|
||||
pointerEvents: "none",
|
||||
whiteSpace: "pre",
|
||||
});
|
||||
document.body.appendChild(div);
|
||||
divRef.current = div;
|
||||
|
||||
return () => {
|
||||
document.body.removeChild(div);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useFrame(({ gl, scene, camera }) => {
|
||||
const renderStart = performance.now();
|
||||
gl.render(scene, camera);
|
||||
renderAcc.current += performance.now() - renderStart;
|
||||
|
||||
fpsFrames.current++;
|
||||
const now = performance.now();
|
||||
const elapsed = now - fpsLastTime.current;
|
||||
if (elapsed >= 1000) {
|
||||
const frames = fpsFrames.current;
|
||||
const fps = Math.round(frames * 1000 / elapsed);
|
||||
const renderAvg = (renderAcc.current / frames).toFixed(3);
|
||||
|
||||
const lines: string[] = [
|
||||
`${fps} FPS gl.render ${renderAvg} ms`,
|
||||
];
|
||||
|
||||
for (const [name, entry] of Object.entries(layerTimings)) {
|
||||
if (entry.frames > 0) {
|
||||
const avg = (entry.acc / entry.frames).toFixed(3);
|
||||
lines.push(`${name} ${avg} ms`);
|
||||
}
|
||||
entry.acc = 0;
|
||||
entry.frames = 0;
|
||||
}
|
||||
|
||||
if (divRef.current) {
|
||||
divRef.current.textContent = lines.join("\n");
|
||||
}
|
||||
|
||||
fpsFrames.current = 0;
|
||||
renderAcc.current = 0;
|
||||
fpsLastTime.current = now;
|
||||
}
|
||||
}, 1);
|
||||
|
||||
return null;
|
||||
};
|
||||
@@ -1,16 +0,0 @@
|
||||
import { useThree } from "@react-three/fiber";
|
||||
import type { Pos3 } from "../../types";
|
||||
import { useLayoutEffect } from "react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
export const CameraSync = observer(function ({ camera }: { camera: Pos3 }) {
|
||||
const { camera: threeCamera } = useThree();
|
||||
|
||||
useLayoutEffect(() => {
|
||||
threeCamera.position.set(camera.position[0], camera.position[1], camera.position[2]);
|
||||
threeCamera.rotation.set(camera.look[0], camera.look[1], camera.look[2]);
|
||||
threeCamera.updateProjectionMatrix();
|
||||
});
|
||||
|
||||
return null;
|
||||
});
|
||||
Reference in New Issue
Block a user