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/[email protected]/examples/jsm/contro
|
|
| 3 |
import {GLTFLoader} from 'https://unpkg.com/[email protected]/examples/jsm/loaders/GLTFLoader.js';
|
| 4 |
import {DragControls} from 'https://unpkg.com/[email protected]/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/[email protected]/examples/jsm/loaders/GLTFLoader.js';
|
| 4 |
import {DragControls} from 'https://unpkg.com/[email protected]/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
|