Spaces:
Paused
Paused
update
Browse files- .gitattributes +1 -0
- static/index.css +73 -0
- static/index.js +85 -22
- static/tutorial.gif +3 -0
.gitattributes
CHANGED
@@ -36,3 +36,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
36 |
objects_occ/background.blend filter=lfs diff=lfs merge=lfs -text
|
37 |
objects_occ/background.obj filter=lfs diff=lfs merge=lfs -text
|
38 |
static/room.glb filter=lfs diff=lfs merge=lfs -text
|
|
|
|
36 |
objects_occ/background.blend filter=lfs diff=lfs merge=lfs -text
|
37 |
objects_occ/background.obj filter=lfs diff=lfs merge=lfs -text
|
38 |
static/room.glb filter=lfs diff=lfs merge=lfs -text
|
39 |
+
static/tutorial.gif filter=lfs diff=lfs merge=lfs -text
|
static/index.css
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*<!-- HTML !-->*/
|
2 |
+
/*<button class="button-73" role="button">Button 73</button>*/
|
3 |
+
|
4 |
+
|
5 |
+
.flex-container {
|
6 |
+
display: flex;
|
7 |
+
height: 100vh; /* Full viewport height */
|
8 |
+
}
|
9 |
+
.left-column {
|
10 |
+
flex: 0 0 200px; /* Fixed width */
|
11 |
+
background-color: #f2f2f2;
|
12 |
+
/* More styles for the left column content */
|
13 |
+
}
|
14 |
+
.right-column {
|
15 |
+
flex-grow: 1; /* Fill the remaining width */
|
16 |
+
background-color: #e8e8e8;
|
17 |
+
/* More styles for the right column content */
|
18 |
+
}
|
19 |
+
/* Style for the Three.js canvas container */
|
20 |
+
#canvas-container {
|
21 |
+
width: 100%;
|
22 |
+
height: 100%;
|
23 |
+
}
|
24 |
+
|
25 |
+
|
26 |
+
|
27 |
+
/* CSS */
|
28 |
+
.container {
|
29 |
+
position: absolute;
|
30 |
+
top: 3%;
|
31 |
+
left: 20%;
|
32 |
+
display: grid;
|
33 |
+
grid-template-columns: repeat(3, 1fr);
|
34 |
+
gap: 30px;
|
35 |
+
}
|
36 |
+
|
37 |
+
|
38 |
+
|
39 |
+
/* CSS */
|
40 |
+
.button-74 {
|
41 |
+
background-color: #fbeee0;
|
42 |
+
border: 2px solid #422800;
|
43 |
+
border-radius: 30px;
|
44 |
+
box-shadow: #422800 4px 4px 0 0;
|
45 |
+
color: #422800;
|
46 |
+
cursor: pointer;
|
47 |
+
display: inline-block;
|
48 |
+
font-weight: 600;
|
49 |
+
font-size: 18px;
|
50 |
+
padding: 0 18px;
|
51 |
+
line-height: 50px;
|
52 |
+
text-align: center;
|
53 |
+
text-decoration: none;
|
54 |
+
user-select: none;
|
55 |
+
-webkit-user-select: none;
|
56 |
+
touch-action: manipulation;
|
57 |
+
}
|
58 |
+
|
59 |
+
.button-74:hover {
|
60 |
+
background-color: #fff;
|
61 |
+
}
|
62 |
+
|
63 |
+
.button-74:active {
|
64 |
+
box-shadow: #422800 2px 2px 0 0;
|
65 |
+
transform: translate(2px, 2px);
|
66 |
+
}
|
67 |
+
|
68 |
+
@media (min-width: 768px) {
|
69 |
+
.button-74 {
|
70 |
+
min-width: 120px;
|
71 |
+
padding: 0 25px;
|
72 |
+
}
|
73 |
+
}
|
static/index.js
CHANGED
@@ -3,27 +3,42 @@ import {OrbitControls} from 'https://unpkg.com/three@0.127.0/examples/jsm/contro
|
|
3 |
import {GLTFLoader} from 'https://unpkg.com/three@0.127.0/examples/jsm/loaders/GLTFLoader.js';
|
4 |
import {DragControls} from 'https://unpkg.com/three@0.127.0/examples/jsm/controls/DragControls.js'
|
5 |
|
6 |
-
|
|
|
7 |
let frameIndex = 0;
|
8 |
let pointCloudData;
|
9 |
-
|
10 |
let pointCloud
|
|
|
|
|
|
|
11 |
const allModelsUrl = ['background.glb', 'basin.glb', 'bed.glb', 'flower.glb', 'kitchen_chair_1.glb', 'kitchen_chair_2.glb', 'office_chair.glb', 'sofa.glb', 'table.glb', 'wc.glb'];
|
12 |
// const allModelsUrl = ['table.glb']
|
13 |
const allModels_dict = {}
|
14 |
const allModels_list = []
|
|
|
15 |
|
16 |
function init() {
|
17 |
scene = new THREE.Scene();
|
18 |
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 100);
|
19 |
-
camera.position.set(9, 6, -9);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
scene.add(camera)
|
21 |
|
22 |
renderer = new THREE.WebGLRenderer({alpha: true, antialias: true});
|
23 |
renderer.setSize(window.innerWidth, window.innerHeight);
|
24 |
renderer.shadowMap.enabled = true;
|
25 |
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap
|
26 |
-
document.body.appendChild(renderer.domElement);
|
|
|
|
|
|
|
27 |
|
28 |
const planeGeometry = new THREE.PlaneGeometry(1000, 1000);
|
29 |
const plane = new THREE.Mesh(planeGeometry, new THREE.MeshBasicMaterial({ color: 0x000000, opacity: 0.25, transparent: true }));
|
@@ -33,13 +48,16 @@ function init() {
|
|
33 |
|
34 |
let points = [];
|
35 |
const line_geometry = new THREE.BufferGeometry().setFromPoints(points);
|
36 |
-
const line_material = new THREE.LineBasicMaterial({ color: 0x0000ff });
|
37 |
const line = new THREE.Line(line_geometry, line_material);
|
38 |
scene.add(line);
|
39 |
|
40 |
|
41 |
-
|
42 |
-
controls.addEventListener('change', render);
|
|
|
|
|
|
|
43 |
|
44 |
// const light = new THREE.HemisphereLight(0xffffbb, 0x080820, 1);
|
45 |
// scene.add(light);
|
@@ -59,7 +77,7 @@ function init() {
|
|
59 |
const geometry = new THREE.BufferGeometry();
|
60 |
const points_frame = new Float32Array(1048 * 3);
|
61 |
geometry.setAttribute('position', new THREE.BufferAttribute(points_frame, 3));
|
62 |
-
const material = new THREE.PointsMaterial({ size: 0.04, color:
|
63 |
pointCloud = new THREE.Points(geometry, material);
|
64 |
scene.add(pointCloud);
|
65 |
|
@@ -69,15 +87,21 @@ function init() {
|
|
69 |
assetLoader.load('/static/'.concat(allModelsUrl[i]), function (gltf) {
|
70 |
const model = gltf.scene;
|
71 |
if (i !== 0) {allModels_dict[allModelsUrl[i]] = model;
|
72 |
-
allModels_list.push(model);
|
|
|
|
|
73 |
|
74 |
scene.add(model);
|
75 |
}, undefined, function (error) {
|
76 |
console.error(error);
|
77 |
});
|
78 |
-
|
79 |
}
|
80 |
|
|
|
|
|
|
|
|
|
|
|
81 |
const dragControls = new DragControls(allModels_list, camera, renderer.domElement);
|
82 |
|
83 |
dragControls.addEventListener('dragstart', function (event) {
|
@@ -115,10 +139,13 @@ function init() {
|
|
115 |
const mouse = new THREE.Vector2();
|
116 |
// Update the mouse vector with the current mouse position
|
117 |
document.addEventListener('pointermove', function (event) {
|
118 |
-
mouse.x = (event.x / renderer.domElement.clientWidth) * 2 - 1;
|
119 |
-
mouse.y = -(event.y / renderer.domElement.clientHeight) * 2 + 1;
|
120 |
|
121 |
-
|
|
|
|
|
|
|
|
|
|
|
122 |
raycaster.setFromCamera(mouse, camera);
|
123 |
const intersects = raycaster.intersectObject(plane);
|
124 |
const point = intersects[0].point;
|
@@ -136,28 +163,53 @@ function init() {
|
|
136 |
isDrawing = false;
|
137 |
controls.enabled = true
|
138 |
dragControls.enabled = true
|
|
|
139 |
|
140 |
}, false);
|
141 |
|
142 |
-
document.getElementById('
|
143 |
isDrawing = false;
|
144 |
|
145 |
|
146 |
function toggleDrawing() {
|
|
|
|
|
|
|
147 |
points = []
|
148 |
isDrawing = true;
|
149 |
-
|
150 |
dragControls.enabled = false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
}
|
152 |
|
153 |
-
document.getElementById('
|
|
|
154 |
function runGeneration() {
|
|
|
|
|
|
|
155 |
const userData = {}
|
156 |
for (let [key, value] of Object.entries(allModels_dict)) {
|
157 |
userData[key] = value.children[0].position
|
158 |
}
|
159 |
userData['trajectory'] = points
|
160 |
-
console.log(userData)
|
161 |
|
162 |
fetch('/move_cube', {
|
163 |
method: 'POST',
|
@@ -169,6 +221,8 @@ function init() {
|
|
169 |
.then(response => response.json())
|
170 |
.then(data => {
|
171 |
pointCloudData = data
|
|
|
|
|
172 |
})
|
173 |
.catch((error) => {
|
174 |
console.error('Error:', error);
|
@@ -190,13 +244,12 @@ function init() {
|
|
190 |
animate();
|
191 |
}
|
192 |
|
|
|
193 |
function updatePointCloud() {
|
194 |
-
if (!pointCloudData) {
|
195 |
|
196 |
-
|
197 |
-
|
198 |
-
// const pointsCloud = new THREE.Points(geometry, material);
|
199 |
-
// scene.add(pointsCloud);
|
200 |
const positions = pointCloud.geometry.attributes.position.array;
|
201 |
const frameData = pointCloudData[frameIndex];
|
202 |
|
@@ -212,8 +265,18 @@ function updatePointCloud() {
|
|
212 |
}
|
213 |
|
214 |
function animate() {
|
|
|
|
|
215 |
requestAnimationFrame(animate);
|
|
|
216 |
updatePointCloud()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
217 |
renderer.render(scene, camera);
|
218 |
}
|
219 |
|
|
|
3 |
import {GLTFLoader} from 'https://unpkg.com/three@0.127.0/examples/jsm/loaders/GLTFLoader.js';
|
4 |
import {DragControls} from 'https://unpkg.com/three@0.127.0/examples/jsm/controls/DragControls.js'
|
5 |
|
6 |
+
|
7 |
+
let scene, camera, renderer, cube, isDrawing, pointerDown, controls;
|
8 |
let frameIndex = 0;
|
9 |
let pointCloudData;
|
10 |
+
const now = Date.now();
|
11 |
let pointCloud
|
12 |
+
let quaternionStart, positionStart;
|
13 |
+
let isGenerating = false;
|
14 |
+
|
15 |
const allModelsUrl = ['background.glb', 'basin.glb', 'bed.glb', 'flower.glb', 'kitchen_chair_1.glb', 'kitchen_chair_2.glb', 'office_chair.glb', 'sofa.glb', 'table.glb', 'wc.glb'];
|
16 |
// const allModelsUrl = ['table.glb']
|
17 |
const allModels_dict = {}
|
18 |
const allModels_list = []
|
19 |
+
let initLoc = {}
|
20 |
|
21 |
function init() {
|
22 |
scene = new THREE.Scene();
|
23 |
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 100);
|
24 |
+
// camera.position.set(9, 6, -9);
|
25 |
+
camera.position.set(3, 13, 0);
|
26 |
+
|
27 |
+
|
28 |
+
// var qm = new THREE.Quaternion(0.1, 0.2, 0.3, 0.4);
|
29 |
+
// camera.quaternion.copy(qm)
|
30 |
+
// camera.updateMatrixWorld();
|
31 |
+
|
32 |
scene.add(camera)
|
33 |
|
34 |
renderer = new THREE.WebGLRenderer({alpha: true, antialias: true});
|
35 |
renderer.setSize(window.innerWidth, window.innerHeight);
|
36 |
renderer.shadowMap.enabled = true;
|
37 |
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap
|
38 |
+
// document.body.appendChild(renderer.domElement);
|
39 |
+
|
40 |
+
const canvasContainer = document.getElementById('canvas-container');
|
41 |
+
canvasContainer.appendChild(renderer.domElement);
|
42 |
|
43 |
const planeGeometry = new THREE.PlaneGeometry(1000, 1000);
|
44 |
const plane = new THREE.Mesh(planeGeometry, new THREE.MeshBasicMaterial({ color: 0x000000, opacity: 0.25, transparent: true }));
|
|
|
48 |
|
49 |
let points = [];
|
50 |
const line_geometry = new THREE.BufferGeometry().setFromPoints(points);
|
51 |
+
const line_material = new THREE.LineBasicMaterial({ color: 0x0000ff, linewidth: 3 });
|
52 |
const line = new THREE.Line(line_geometry, line_material);
|
53 |
scene.add(line);
|
54 |
|
55 |
|
56 |
+
controls = new OrbitControls(camera, renderer.domElement);
|
57 |
+
// controls.addEventListener('change', render);
|
58 |
+
|
59 |
+
// const quaternion = new THREE.Quaternion(-0.707, 0, 0, 0.707)
|
60 |
+
// camera.quaternion.copy(quaternion)
|
61 |
|
62 |
// const light = new THREE.HemisphereLight(0xffffbb, 0x080820, 1);
|
63 |
// scene.add(light);
|
|
|
77 |
const geometry = new THREE.BufferGeometry();
|
78 |
const points_frame = new Float32Array(1048 * 3);
|
79 |
geometry.setAttribute('position', new THREE.BufferAttribute(points_frame, 3));
|
80 |
+
const material = new THREE.PointsMaterial({ size: 0.04, color: 0x2020e0 });
|
81 |
pointCloud = new THREE.Points(geometry, material);
|
82 |
scene.add(pointCloud);
|
83 |
|
|
|
87 |
assetLoader.load('/static/'.concat(allModelsUrl[i]), function (gltf) {
|
88 |
const model = gltf.scene;
|
89 |
if (i !== 0) {allModels_dict[allModelsUrl[i]] = model;
|
90 |
+
allModels_list.push(model);
|
91 |
+
initLoc[allModelsUrl[i]] = model.children[0].position.clone()
|
92 |
+
}
|
93 |
|
94 |
scene.add(model);
|
95 |
}, undefined, function (error) {
|
96 |
console.error(error);
|
97 |
});
|
|
|
98 |
}
|
99 |
|
100 |
+
// for (let [key, value] of Object.entries(allModels_dict)) {
|
101 |
+
// initLoc[key] = value.children[0].position
|
102 |
+
// }
|
103 |
+
|
104 |
+
|
105 |
const dragControls = new DragControls(allModels_list, camera, renderer.domElement);
|
106 |
|
107 |
dragControls.addEventListener('dragstart', function (event) {
|
|
|
139 |
const mouse = new THREE.Vector2();
|
140 |
// Update the mouse vector with the current mouse position
|
141 |
document.addEventListener('pointermove', function (event) {
|
|
|
|
|
142 |
|
143 |
+
const rect = renderer.domElement.getBoundingClientRect();
|
144 |
+
|
145 |
+
mouse.x = ((event.x - rect.left) / rect.width) * 2 - 1;
|
146 |
+
mouse.y = -((event.y - rect.top) / rect.height) * 2 + 1;
|
147 |
+
|
148 |
+
if (isDrawing && pointerDown && points.length < 500) {
|
149 |
raycaster.setFromCamera(mouse, camera);
|
150 |
const intersects = raycaster.intersectObject(plane);
|
151 |
const point = intersects[0].point;
|
|
|
163 |
isDrawing = false;
|
164 |
controls.enabled = true
|
165 |
dragControls.enabled = true
|
166 |
+
document.getElementById('toggleDraw').innerHTML = "Draw Trajectory";
|
167 |
|
168 |
}, false);
|
169 |
|
170 |
+
document.getElementById('toggleDraw').addEventListener('click', toggleDrawing);
|
171 |
isDrawing = false;
|
172 |
|
173 |
|
174 |
function toggleDrawing() {
|
175 |
+
controls.enabled = false
|
176 |
+
quaternionStart = camera.quaternion.clone();
|
177 |
+
positionStart = camera.position.clone();
|
178 |
points = []
|
179 |
isDrawing = true;
|
180 |
+
|
181 |
dragControls.enabled = false
|
182 |
+
|
183 |
+
document.getElementById('toggleDraw').innerHTML = "Drawing";
|
184 |
+
}
|
185 |
+
|
186 |
+
document.getElementById('reset').addEventListener('click', reset);
|
187 |
+
|
188 |
+
function reset() {
|
189 |
+
points = [];
|
190 |
+
line_geometry.setFromPoints(points);
|
191 |
+
|
192 |
+
for (let [key, value] of Object.entries(allModels_dict)) {
|
193 |
+
value.children[0].position.set(initLoc[key].x, initLoc[key].y, initLoc[key].z);
|
194 |
+
}
|
195 |
+
document.getElementById('toggleDraw').innerHTML = "Draw Trajectory";
|
196 |
+
pointCloudData = null;
|
197 |
+
pointCloud.geometry.attributes.position.array = new Float32Array(1048 * 3);
|
198 |
+
pointCloud.geometry.attributes.position.needsUpdate = true;
|
199 |
+
render()
|
200 |
}
|
201 |
|
202 |
+
document.getElementById('generateMotion').addEventListener('click', runGeneration);
|
203 |
+
|
204 |
function runGeneration() {
|
205 |
+
if (!points.length || isGenerating) {return}
|
206 |
+
isGenerating = true;
|
207 |
+
|
208 |
const userData = {}
|
209 |
for (let [key, value] of Object.entries(allModels_dict)) {
|
210 |
userData[key] = value.children[0].position
|
211 |
}
|
212 |
userData['trajectory'] = points
|
|
|
213 |
|
214 |
fetch('/move_cube', {
|
215 |
method: 'POST',
|
|
|
221 |
.then(response => response.json())
|
222 |
.then(data => {
|
223 |
pointCloudData = data
|
224 |
+
document.getElementById("generateMotion").innerHTML = "Generate Motion";
|
225 |
+
isGenerating = false;
|
226 |
})
|
227 |
.catch((error) => {
|
228 |
console.error('Error:', error);
|
|
|
244 |
animate();
|
245 |
}
|
246 |
|
247 |
+
|
248 |
function updatePointCloud() {
|
249 |
+
if (!pointCloudData) {
|
250 |
|
251 |
+
return;
|
252 |
+
}
|
|
|
|
|
253 |
const positions = pointCloud.geometry.attributes.position.array;
|
254 |
const frameData = pointCloudData[frameIndex];
|
255 |
|
|
|
265 |
}
|
266 |
|
267 |
function animate() {
|
268 |
+
// requestAnimationFrame(animate);
|
269 |
+
setTimeout(() => {
|
270 |
requestAnimationFrame(animate);
|
271 |
+
}, 1000 / 25);
|
272 |
updatePointCloud()
|
273 |
+
|
274 |
+
if (isGenerating) {
|
275 |
+
let dotNum = parseInt((Date.now() - now) / 500) % 8
|
276 |
+
const dot = Array(dotNum * 2).join('.')
|
277 |
+
document.getElementById("generateMotion").innerHTML = "Loading" + dot;
|
278 |
+
}
|
279 |
+
|
280 |
renderer.render(scene, camera);
|
281 |
}
|
282 |
|
static/tutorial.gif
ADDED
Git LFS Details
|