diff --git a/src/components/EditPage/PageData/Edit3d.jsx b/src/components/EditPage/PageData/Edit3d.jsx
index 61b4213..2c0c0f7 100644
--- a/src/components/EditPage/PageData/Edit3d.jsx
+++ b/src/components/EditPage/PageData/Edit3d.jsx
@@ -7,7 +7,7 @@ import EditObjLoader from './Edit3d/EditObjLoader';
import EditGltfLoader from './Edit3d/EditGltfLoader';
import { objectSizeState } from '../../../store/toolState';
-function Edit3d({ objecturl }) {
+function Edit3d({ objecturl, setObjectValue, pageRendering }) {
const { camera } = useThree();
const dataSize = useRecoilValue(objectSizeState);
@@ -50,7 +50,7 @@ function Edit3d({ objecturl }) {
return (
<>
-
+
) : url?.extension === 'gltf' ? (
) : null,
)}
diff --git a/src/components/EditPage/PageData/Edit3d/EditGltfLoader.jsx b/src/components/EditPage/PageData/Edit3d/EditGltfLoader.jsx
index 496d9ec..edc6cb6 100644
--- a/src/components/EditPage/PageData/Edit3d/EditGltfLoader.jsx
+++ b/src/components/EditPage/PageData/Edit3d/EditGltfLoader.jsx
@@ -1,13 +1,23 @@
import React, { useRef, useEffect, useState } from 'react';
import { useFrame, useThree } from '@react-three/fiber';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
-import { Color, Box3, Vector3, AxesHelper } from 'three';
+import { Color, Box3, Vector3 } from 'three';
import { useRecoilState } from 'recoil';
-import { DragControls } from 'three/examples/jsm/controls/DragControls';
+
import { LodingState } from '../../../../store/modalState';
import useKeyDown from '../../../../hooks/EditPage/Handlers/useKeyDown';
+import useObjectDrag from '../../../../hooks/EditPage/useObjectDrag';
-function EditGltfLoader({ objecturl, size, x, y, z, setIsDragging }) {
+function EditGltfLoader({
+ objecturl,
+ size,
+ x,
+ y,
+ z,
+ setIsDragging,
+ setObjectValue,
+ pageRendering,
+}) {
const modelRef = useRef();
const { camera, scene, gl } = useThree();
const [loadingValue, setLoadingValue] = useRecoilState(LodingState);
@@ -15,7 +25,6 @@ function EditGltfLoader({ objecturl, size, x, y, z, setIsDragging }) {
const [initialScale, setInitialScale] = useState([1, 1, 1]);
const movement = useRef({ forward: 0, right: 0, up: 0 });
const gltfUrl = typeof objecturl === 'string' ? objecturl : objecturl.gltf;
- const controlsRef = useRef();
useEffect(() => {
scene.background = new Color('#FFFFFF');
@@ -40,6 +49,8 @@ function EditGltfLoader({ objecturl, size, x, y, z, setIsDragging }) {
setGltf(loadedGltf);
setInitialScale([scale, scale, scale]);
+ loadedGltf.scene.position.set(x, y, z); // 초기 위치 설정
+
setLoadingValue(false);
},
undefined,
@@ -62,37 +73,17 @@ function EditGltfLoader({ objecturl, size, x, y, z, setIsDragging }) {
});
useKeyDown(movement, modelRef);
- useEffect(() => {
- if (modelRef.current) {
- controlsRef.current = new DragControls(
- [modelRef.current],
- camera,
- gl.domElement,
- );
-
- controlsRef.current.addEventListener('dragstart', (event) => {
- event.object.material.emissive.set(0xaaaaaa);
- setIsDragging(true);
- });
- controlsRef.current.addEventListener('dragend', (event) => {
- event.object.material.emissive.set(0x000000);
- setIsDragging(false);
- });
+ useObjectDrag({
+ modelRef,
+ camera,
+ domElement: gl.domElement,
+ setIsDragging,
+ setObjectValue,
+ pageRendering,
+ objectId: objecturl.id,
+ });
- return () => {
- controlsRef.current.dispose();
- };
- }
- return undefined;
- }, [camera, gl]);
- useEffect(() => {
- const axesHelper = new AxesHelper(100);
- scene.add(axesHelper);
- return () => {
- scene.remove(axesHelper);
- };
- }, [scene]);
return (
{gltf ? (
diff --git a/src/components/EditPage/PageData/Edit3d/EditObjLoader.jsx b/src/components/EditPage/PageData/Edit3d/EditObjLoader.jsx
index 650164d..13860ea 100644
--- a/src/components/EditPage/PageData/Edit3d/EditObjLoader.jsx
+++ b/src/components/EditPage/PageData/Edit3d/EditObjLoader.jsx
@@ -6,10 +6,20 @@ import { useRecoilState } from 'recoil';
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader';
import { LodingState } from '../../../../store/modalState';
import useKeyDown from '../../../../hooks/EditPage/Handlers/useKeyDown';
-
-function EditObjLoader({ objecturl, size, x, y, z }) {
+import useObjectDrag from '../../../../hooks/EditPage/useObjectDrag';
+
+function EditObjLoader({
+ objecturl,
+ size,
+ x,
+ y,
+ z,
+ setIsDragging,
+ setObjectValue,
+ pageRendering,
+}) {
const modelRef = useRef();
- const { camera } = useThree();
+ const { camera, gl } = useThree();
const [loadingValue, setLoadingValue] = useRecoilState(LodingState);
const [object, setObject] = useState(null);
const [initialScale, setInitialScale] = useState([1, 1, 1]);
@@ -27,6 +37,7 @@ function EditObjLoader({ objecturl, size, x, y, z }) {
setObject(null);
return;
}
+
setLoadingValue(true);
const materialUrl = objecturl?.mtl || null;
@@ -63,12 +74,6 @@ function EditObjLoader({ objecturl, size, x, y, z }) {
loadModel();
}, [objecturl, setLoadingValue]);
- useEffect(() => {
- if (object) {
- setLoadingValue(false);
- }
- }, [object, setLoadingValue]);
-
useFrame(() => {
if (!modelRef.current) return;
const speed = 0.1;
@@ -83,6 +88,16 @@ function EditObjLoader({ objecturl, size, x, y, z }) {
useKeyDown(movement, modelRef);
+ useObjectDrag({
+ modelRef,
+ camera,
+ domElement: gl.domElement,
+ setIsDragging,
+ setObjectValue,
+ pageRendering,
+ objectId: objecturl.id,
+ });
+
return (
{object ? (
diff --git a/src/components/Modal/atom/Test.jsx b/src/components/Modal/atom/Test.jsx
deleted file mode 100644
index 187ecee..0000000
--- a/src/components/Modal/atom/Test.jsx
+++ /dev/null
@@ -1,76 +0,0 @@
-import React, { useEffect, useRef, useState } from 'react';
-import { useThree } from '@react-three/fiber';
-import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
-import { Color, Box3, Vector3 } from 'three';
-import { useRecoilState } from 'recoil';
-import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader';
-import { LodingState } from '../../../store/modalState';
-
-function TestOBJ({ objecturl, x, y, z }) {
- const modelRef = useRef();
- const [loadingValue, setLoadingValue] = useRecoilState(LodingState);
- const [object, setObject] = useState(null);
-
- const { scene } = useThree();
-
- useEffect(() => {
- scene.background = new Color('#FFFFFF');
- }, [scene]);
-
- useEffect(() => {
- if (!objecturl?.obj) {
- setLoadingValue(false);
- setObject(null);
- return;
- }
- setLoadingValue(true);
-
- const materialUrl = objecturl?.mtl || null;
- const loadUrl = objecturl?.obj || null;
-
- const loadModel = () => {
- const objLoader = new OBJLoader();
- const onLoad = (obj) => {
- // 모델의 경계 계산
- const box = new Box3().setFromObject(obj);
- const size = new Vector3();
- box.getSize(size);
- const maxDimension = Math.max(size.x, size.y, size.z);
-
- const scale = 5 / maxDimension;
-
- obj.scale.set(scale, scale, scale);
-
- setObject(obj);
- setLoadingValue(false);
- };
-
- if (materialUrl) {
- const mtlLoader = new MTLLoader();
- mtlLoader.load(materialUrl, (materials) => {
- materials.preload();
- objLoader.setMaterials(materials);
- objLoader.load(loadUrl, onLoad);
- });
- } else {
- objLoader.load(loadUrl, onLoad);
- }
- };
-
- loadModel();
- }, [objecturl, setLoadingValue]);
-
- useEffect(() => {
- if (object) {
- setLoadingValue(false);
- }
- }, [object, setLoadingValue]);
-
- return (
-
- {object ? : null}
-
- );
-}
-
-export default TestOBJ;
diff --git a/src/hooks/AddItem/useObject.js b/src/hooks/AddItem/useObject.js
index bf1e79a..1806fa5 100644
--- a/src/hooks/AddItem/useObject.js
+++ b/src/hooks/AddItem/useObject.js
@@ -30,7 +30,7 @@ const useObject = () => {
textures: texturesUrl,
size: 0.25,
x: getRandomCoordinate(),
- y: getRandomCoordinate(),
+ y: 0,
z: getRandomCoordinate(),
};
const updatedImages = {
diff --git a/src/hooks/EditPage/useItemValue.js b/src/hooks/EditPage/useItemValue.js
index 8545fa7..7093728 100644
--- a/src/hooks/EditPage/useItemValue.js
+++ b/src/hooks/EditPage/useItemValue.js
@@ -1,4 +1,4 @@
-import { useRecoilState, useRecoilValue } from 'recoil';
+import { useRecoilState } from 'recoil';
import {
imageList,
object3dState,
@@ -7,13 +7,14 @@ import {
} from '../../store/recoil';
const useItemValue = () => {
- const objectValue = useRecoilValue(object3dState);
+ const [objectValue, setObjectValue] = useRecoilState(object3dState);
const [shapeValue, setShapeValue] = useRecoilState(shapeList);
const [textValue, setTextValue] = useRecoilState(textList);
const [imgValue, setImgValue] = useRecoilState(imageList);
return {
objectValue,
+ setObjectValue,
shapeValue,
setShapeValue,
textValue,
diff --git a/src/hooks/EditPage/useObjectDrag.js b/src/hooks/EditPage/useObjectDrag.js
new file mode 100644
index 0000000..4e73521
--- /dev/null
+++ b/src/hooks/EditPage/useObjectDrag.js
@@ -0,0 +1,89 @@
+import { useRef, useEffect } from 'react';
+import { DragControls } from 'three/examples/jsm/controls/DragControls';
+import { Vector3 } from 'three';
+
+const useObjectDrag = ({
+ modelRef,
+ camera,
+ domElement,
+ setIsDragging,
+ setObjectValue,
+ pageRendering,
+ objectId,
+ scaleFactor = 0.05,
+}) => {
+ const controlsRef = useRef();
+ const startPosition = useRef(new Vector3());
+ const deltaPosition = useRef(new Vector3());
+
+ const handlePositionChange = (id, axis, value) => {
+ setObjectValue((prev) => ({
+ ...prev,
+ [pageRendering]: prev[pageRendering].map((obj) =>
+ obj.id === id ? { ...obj, [axis]: value } : obj,
+ ),
+ }));
+ };
+
+ useEffect(() => {
+ if (modelRef.current) {
+ controlsRef.current = new DragControls(
+ [modelRef.current],
+ camera,
+ domElement,
+ );
+
+ controlsRef.current.addEventListener('dragstart', (event) => {
+ if (event.object.material && event.object.material.emissive) {
+ event.object.material.emissive.set(0xaaaaaa);
+ }
+ if (typeof setIsDragging === 'function') {
+ setIsDragging(true);
+ }
+ startPosition.current.copy(event.object.position);
+ });
+
+ controlsRef.current.addEventListener('drag', (event) => {
+ const { object } = event;
+ object.position.y = 0; // y축 고정
+
+ deltaPosition.current.set(
+ (object.position.x - startPosition.current.x) * scaleFactor,
+ 0,
+ (object.position.z - startPosition.current.z) * scaleFactor,
+ );
+
+ object.position.x = startPosition.current.x + deltaPosition.current.x;
+ object.position.z = startPosition.current.z + deltaPosition.current.z;
+
+ // 여기에서 실시간으로 위치를 저장
+ handlePositionChange(objectId, 'x', Math.round(object.position.x));
+ handlePositionChange(objectId, 'z', Math.round(object.position.z));
+ });
+
+ controlsRef.current.addEventListener('dragend', (event) => {
+ const { object } = event;
+
+ if (object.material && object.material.emissive) {
+ object.material.emissive.set(0x000000);
+ }
+ if (typeof setIsDragging === 'function') {
+ setIsDragging(false);
+ }
+ // 드래그가 끝난 후 최종 위치를 저장
+ handlePositionChange(objectId, 'x', Math.round(object.position.x));
+ handlePositionChange(objectId, 'z', Math.round(object.position.z));
+ });
+
+ return () => {
+ controlsRef.current.dispose();
+ };
+ }
+ // 명시적으로 undefined 반환
+ return undefined;
+ }, [camera, domElement, modelRef]);
+
+ return controlsRef;
+};
+
+export default useObjectDrag;
diff --git a/src/pages/EditPage.jsx b/src/pages/EditPage.jsx
index edc4fc9..124453c 100644
--- a/src/pages/EditPage.jsx
+++ b/src/pages/EditPage.jsx
@@ -36,6 +36,7 @@ function EditPage() {
const {
objectValue,
+ setObjectValue,
shapeValue,
setShapeValue,
textValue,
@@ -187,7 +188,11 @@ function EditPage() {
}
}
>
-
+
);
}